18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
28c2ecf20Sopenharmony_ci/*
38c2ecf20Sopenharmony_ci * AD5024, AD5025, AD5044, AD5045, AD5064, AD5064-1, AD5065, AD5625, AD5625R,
48c2ecf20Sopenharmony_ci * AD5627, AD5627R, AD5628, AD5629R, AD5645R, AD5647R, AD5648, AD5665, AD5665R,
58c2ecf20Sopenharmony_ci * AD5666, AD5667, AD5667R, AD5668, AD5669R, LTC2606, LTC2607, LTC2609, LTC2616,
68c2ecf20Sopenharmony_ci * LTC2617, LTC2619, LTC2626, LTC2627, LTC2629, LTC2631, LTC2633, LTC2635
78c2ecf20Sopenharmony_ci * Digital to analog converters driver
88c2ecf20Sopenharmony_ci *
98c2ecf20Sopenharmony_ci * Copyright 2011 Analog Devices Inc.
108c2ecf20Sopenharmony_ci */
118c2ecf20Sopenharmony_ci
128c2ecf20Sopenharmony_ci#include <linux/device.h>
138c2ecf20Sopenharmony_ci#include <linux/err.h>
148c2ecf20Sopenharmony_ci#include <linux/module.h>
158c2ecf20Sopenharmony_ci#include <linux/kernel.h>
168c2ecf20Sopenharmony_ci#include <linux/spi/spi.h>
178c2ecf20Sopenharmony_ci#include <linux/i2c.h>
188c2ecf20Sopenharmony_ci#include <linux/slab.h>
198c2ecf20Sopenharmony_ci#include <linux/sysfs.h>
208c2ecf20Sopenharmony_ci#include <linux/regulator/consumer.h>
218c2ecf20Sopenharmony_ci#include <asm/unaligned.h>
228c2ecf20Sopenharmony_ci
238c2ecf20Sopenharmony_ci#include <linux/iio/iio.h>
248c2ecf20Sopenharmony_ci#include <linux/iio/sysfs.h>
258c2ecf20Sopenharmony_ci
268c2ecf20Sopenharmony_ci#define AD5064_MAX_DAC_CHANNELS			8
278c2ecf20Sopenharmony_ci#define AD5064_MAX_VREFS			4
288c2ecf20Sopenharmony_ci
298c2ecf20Sopenharmony_ci#define AD5064_ADDR(x)				((x) << 20)
308c2ecf20Sopenharmony_ci#define AD5064_CMD(x)				((x) << 24)
318c2ecf20Sopenharmony_ci
328c2ecf20Sopenharmony_ci#define AD5064_ADDR_ALL_DAC			0xF
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N		0x0
358c2ecf20Sopenharmony_ci#define AD5064_CMD_UPDATE_DAC_N			0x1
368c2ecf20Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N_UPDATE_ALL	0x2
378c2ecf20Sopenharmony_ci#define AD5064_CMD_WRITE_INPUT_N_UPDATE_N	0x3
388c2ecf20Sopenharmony_ci#define AD5064_CMD_POWERDOWN_DAC		0x4
398c2ecf20Sopenharmony_ci#define AD5064_CMD_CLEAR			0x5
408c2ecf20Sopenharmony_ci#define AD5064_CMD_LDAC_MASK			0x6
418c2ecf20Sopenharmony_ci#define AD5064_CMD_RESET			0x7
428c2ecf20Sopenharmony_ci#define AD5064_CMD_CONFIG			0x8
438c2ecf20Sopenharmony_ci
448c2ecf20Sopenharmony_ci#define AD5064_CMD_RESET_V2			0x5
458c2ecf20Sopenharmony_ci#define AD5064_CMD_CONFIG_V2			0x7
468c2ecf20Sopenharmony_ci
478c2ecf20Sopenharmony_ci#define AD5064_CONFIG_DAISY_CHAIN_ENABLE	BIT(1)
488c2ecf20Sopenharmony_ci#define AD5064_CONFIG_INT_VREF_ENABLE		BIT(0)
498c2ecf20Sopenharmony_ci
508c2ecf20Sopenharmony_ci#define AD5064_LDAC_PWRDN_NONE			0x0
518c2ecf20Sopenharmony_ci#define AD5064_LDAC_PWRDN_1K			0x1
528c2ecf20Sopenharmony_ci#define AD5064_LDAC_PWRDN_100K			0x2
538c2ecf20Sopenharmony_ci#define AD5064_LDAC_PWRDN_3STATE		0x3
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_ci/**
568c2ecf20Sopenharmony_ci * enum ad5064_regmap_type - Register layout variant
578c2ecf20Sopenharmony_ci * @AD5064_REGMAP_ADI: Old Analog Devices register map layout
588c2ecf20Sopenharmony_ci * @AD5064_REGMAP_ADI2: New Analog Devices register map layout
598c2ecf20Sopenharmony_ci * @AD5064_REGMAP_LTC: LTC register map layout
608c2ecf20Sopenharmony_ci */
618c2ecf20Sopenharmony_cienum ad5064_regmap_type {
628c2ecf20Sopenharmony_ci	AD5064_REGMAP_ADI,
638c2ecf20Sopenharmony_ci	AD5064_REGMAP_ADI2,
648c2ecf20Sopenharmony_ci	AD5064_REGMAP_LTC,
658c2ecf20Sopenharmony_ci};
668c2ecf20Sopenharmony_ci
678c2ecf20Sopenharmony_ci/**
688c2ecf20Sopenharmony_ci * struct ad5064_chip_info - chip specific information
698c2ecf20Sopenharmony_ci * @shared_vref:	whether the vref supply is shared between channels
708c2ecf20Sopenharmony_ci * @internal_vref:	internal reference voltage. 0 if the chip has no
718c2ecf20Sopenharmony_ci *			internal vref.
728c2ecf20Sopenharmony_ci * @channels:		channel specification
738c2ecf20Sopenharmony_ci * @num_channels:	number of channels
748c2ecf20Sopenharmony_ci * @regmap_type:	register map layout variant
758c2ecf20Sopenharmony_ci */
768c2ecf20Sopenharmony_ci
778c2ecf20Sopenharmony_cistruct ad5064_chip_info {
788c2ecf20Sopenharmony_ci	bool shared_vref;
798c2ecf20Sopenharmony_ci	unsigned long internal_vref;
808c2ecf20Sopenharmony_ci	const struct iio_chan_spec *channels;
818c2ecf20Sopenharmony_ci	unsigned int num_channels;
828c2ecf20Sopenharmony_ci	enum ad5064_regmap_type regmap_type;
838c2ecf20Sopenharmony_ci};
848c2ecf20Sopenharmony_ci
858c2ecf20Sopenharmony_cistruct ad5064_state;
868c2ecf20Sopenharmony_ci
878c2ecf20Sopenharmony_citypedef int (*ad5064_write_func)(struct ad5064_state *st, unsigned int cmd,
888c2ecf20Sopenharmony_ci		unsigned int addr, unsigned int val);
898c2ecf20Sopenharmony_ci
908c2ecf20Sopenharmony_ci/**
918c2ecf20Sopenharmony_ci * struct ad5064_state - driver instance specific data
928c2ecf20Sopenharmony_ci * @dev:		the device for this driver instance
938c2ecf20Sopenharmony_ci * @chip_info:		chip model specific constants, available modes etc
948c2ecf20Sopenharmony_ci * @vref_reg:		vref supply regulators
958c2ecf20Sopenharmony_ci * @pwr_down:		whether channel is powered down
968c2ecf20Sopenharmony_ci * @pwr_down_mode:	channel's current power down mode
978c2ecf20Sopenharmony_ci * @dac_cache:		current DAC raw value (chip does not support readback)
988c2ecf20Sopenharmony_ci * @use_internal_vref:	set to true if the internal reference voltage should be
998c2ecf20Sopenharmony_ci *			used.
1008c2ecf20Sopenharmony_ci * @write:		register write callback
1018c2ecf20Sopenharmony_ci * @lock:		maintain consistency between cached and dev state
1028c2ecf20Sopenharmony_ci * @data:		i2c/spi transfer buffers
1038c2ecf20Sopenharmony_ci */
1048c2ecf20Sopenharmony_ci
1058c2ecf20Sopenharmony_cistruct ad5064_state {
1068c2ecf20Sopenharmony_ci	struct device			*dev;
1078c2ecf20Sopenharmony_ci	const struct ad5064_chip_info	*chip_info;
1088c2ecf20Sopenharmony_ci	struct regulator_bulk_data	vref_reg[AD5064_MAX_VREFS];
1098c2ecf20Sopenharmony_ci	bool				pwr_down[AD5064_MAX_DAC_CHANNELS];
1108c2ecf20Sopenharmony_ci	u8				pwr_down_mode[AD5064_MAX_DAC_CHANNELS];
1118c2ecf20Sopenharmony_ci	unsigned int			dac_cache[AD5064_MAX_DAC_CHANNELS];
1128c2ecf20Sopenharmony_ci	bool				use_internal_vref;
1138c2ecf20Sopenharmony_ci
1148c2ecf20Sopenharmony_ci	ad5064_write_func		write;
1158c2ecf20Sopenharmony_ci	struct mutex lock;
1168c2ecf20Sopenharmony_ci
1178c2ecf20Sopenharmony_ci	/*
1188c2ecf20Sopenharmony_ci	 * DMA (thus cache coherency maintenance) requires the
1198c2ecf20Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
1208c2ecf20Sopenharmony_ci	 */
1218c2ecf20Sopenharmony_ci	union {
1228c2ecf20Sopenharmony_ci		u8 i2c[3];
1238c2ecf20Sopenharmony_ci		__be32 spi;
1248c2ecf20Sopenharmony_ci	} data ____cacheline_aligned;
1258c2ecf20Sopenharmony_ci};
1268c2ecf20Sopenharmony_ci
1278c2ecf20Sopenharmony_cienum ad5064_type {
1288c2ecf20Sopenharmony_ci	ID_AD5024,
1298c2ecf20Sopenharmony_ci	ID_AD5025,
1308c2ecf20Sopenharmony_ci	ID_AD5044,
1318c2ecf20Sopenharmony_ci	ID_AD5045,
1328c2ecf20Sopenharmony_ci	ID_AD5064,
1338c2ecf20Sopenharmony_ci	ID_AD5064_1,
1348c2ecf20Sopenharmony_ci	ID_AD5065,
1358c2ecf20Sopenharmony_ci	ID_AD5625,
1368c2ecf20Sopenharmony_ci	ID_AD5625R_1V25,
1378c2ecf20Sopenharmony_ci	ID_AD5625R_2V5,
1388c2ecf20Sopenharmony_ci	ID_AD5627,
1398c2ecf20Sopenharmony_ci	ID_AD5627R_1V25,
1408c2ecf20Sopenharmony_ci	ID_AD5627R_2V5,
1418c2ecf20Sopenharmony_ci	ID_AD5628_1,
1428c2ecf20Sopenharmony_ci	ID_AD5628_2,
1438c2ecf20Sopenharmony_ci	ID_AD5629_1,
1448c2ecf20Sopenharmony_ci	ID_AD5629_2,
1458c2ecf20Sopenharmony_ci	ID_AD5645R_1V25,
1468c2ecf20Sopenharmony_ci	ID_AD5645R_2V5,
1478c2ecf20Sopenharmony_ci	ID_AD5647R_1V25,
1488c2ecf20Sopenharmony_ci	ID_AD5647R_2V5,
1498c2ecf20Sopenharmony_ci	ID_AD5648_1,
1508c2ecf20Sopenharmony_ci	ID_AD5648_2,
1518c2ecf20Sopenharmony_ci	ID_AD5665,
1528c2ecf20Sopenharmony_ci	ID_AD5665R_1V25,
1538c2ecf20Sopenharmony_ci	ID_AD5665R_2V5,
1548c2ecf20Sopenharmony_ci	ID_AD5666_1,
1558c2ecf20Sopenharmony_ci	ID_AD5666_2,
1568c2ecf20Sopenharmony_ci	ID_AD5667,
1578c2ecf20Sopenharmony_ci	ID_AD5667R_1V25,
1588c2ecf20Sopenharmony_ci	ID_AD5667R_2V5,
1598c2ecf20Sopenharmony_ci	ID_AD5668_1,
1608c2ecf20Sopenharmony_ci	ID_AD5668_2,
1618c2ecf20Sopenharmony_ci	ID_AD5669_1,
1628c2ecf20Sopenharmony_ci	ID_AD5669_2,
1638c2ecf20Sopenharmony_ci	ID_LTC2606,
1648c2ecf20Sopenharmony_ci	ID_LTC2607,
1658c2ecf20Sopenharmony_ci	ID_LTC2609,
1668c2ecf20Sopenharmony_ci	ID_LTC2616,
1678c2ecf20Sopenharmony_ci	ID_LTC2617,
1688c2ecf20Sopenharmony_ci	ID_LTC2619,
1698c2ecf20Sopenharmony_ci	ID_LTC2626,
1708c2ecf20Sopenharmony_ci	ID_LTC2627,
1718c2ecf20Sopenharmony_ci	ID_LTC2629,
1728c2ecf20Sopenharmony_ci	ID_LTC2631_L12,
1738c2ecf20Sopenharmony_ci	ID_LTC2631_H12,
1748c2ecf20Sopenharmony_ci	ID_LTC2631_L10,
1758c2ecf20Sopenharmony_ci	ID_LTC2631_H10,
1768c2ecf20Sopenharmony_ci	ID_LTC2631_L8,
1778c2ecf20Sopenharmony_ci	ID_LTC2631_H8,
1788c2ecf20Sopenharmony_ci	ID_LTC2633_L12,
1798c2ecf20Sopenharmony_ci	ID_LTC2633_H12,
1808c2ecf20Sopenharmony_ci	ID_LTC2633_L10,
1818c2ecf20Sopenharmony_ci	ID_LTC2633_H10,
1828c2ecf20Sopenharmony_ci	ID_LTC2633_L8,
1838c2ecf20Sopenharmony_ci	ID_LTC2633_H8,
1848c2ecf20Sopenharmony_ci	ID_LTC2635_L12,
1858c2ecf20Sopenharmony_ci	ID_LTC2635_H12,
1868c2ecf20Sopenharmony_ci	ID_LTC2635_L10,
1878c2ecf20Sopenharmony_ci	ID_LTC2635_H10,
1888c2ecf20Sopenharmony_ci	ID_LTC2635_L8,
1898c2ecf20Sopenharmony_ci	ID_LTC2635_H8,
1908c2ecf20Sopenharmony_ci};
1918c2ecf20Sopenharmony_ci
1928c2ecf20Sopenharmony_cistatic int ad5064_write(struct ad5064_state *st, unsigned int cmd,
1938c2ecf20Sopenharmony_ci	unsigned int addr, unsigned int val, unsigned int shift)
1948c2ecf20Sopenharmony_ci{
1958c2ecf20Sopenharmony_ci	val <<= shift;
1968c2ecf20Sopenharmony_ci
1978c2ecf20Sopenharmony_ci	return st->write(st, cmd, addr, val);
1988c2ecf20Sopenharmony_ci}
1998c2ecf20Sopenharmony_ci
2008c2ecf20Sopenharmony_cistatic int ad5064_sync_powerdown_mode(struct ad5064_state *st,
2018c2ecf20Sopenharmony_ci	const struct iio_chan_spec *chan)
2028c2ecf20Sopenharmony_ci{
2038c2ecf20Sopenharmony_ci	unsigned int val, address;
2048c2ecf20Sopenharmony_ci	unsigned int shift;
2058c2ecf20Sopenharmony_ci	int ret;
2068c2ecf20Sopenharmony_ci
2078c2ecf20Sopenharmony_ci	if (st->chip_info->regmap_type == AD5064_REGMAP_LTC) {
2088c2ecf20Sopenharmony_ci		val = 0;
2098c2ecf20Sopenharmony_ci		address = chan->address;
2108c2ecf20Sopenharmony_ci	} else {
2118c2ecf20Sopenharmony_ci		if (st->chip_info->regmap_type == AD5064_REGMAP_ADI2)
2128c2ecf20Sopenharmony_ci			shift = 4;
2138c2ecf20Sopenharmony_ci		else
2148c2ecf20Sopenharmony_ci			shift = 8;
2158c2ecf20Sopenharmony_ci
2168c2ecf20Sopenharmony_ci		val = (0x1 << chan->address);
2178c2ecf20Sopenharmony_ci		address = 0;
2188c2ecf20Sopenharmony_ci
2198c2ecf20Sopenharmony_ci		if (st->pwr_down[chan->channel])
2208c2ecf20Sopenharmony_ci			val |= st->pwr_down_mode[chan->channel] << shift;
2218c2ecf20Sopenharmony_ci	}
2228c2ecf20Sopenharmony_ci
2238c2ecf20Sopenharmony_ci	ret = ad5064_write(st, AD5064_CMD_POWERDOWN_DAC, address, val, 0);
2248c2ecf20Sopenharmony_ci
2258c2ecf20Sopenharmony_ci	return ret;
2268c2ecf20Sopenharmony_ci}
2278c2ecf20Sopenharmony_ci
2288c2ecf20Sopenharmony_cistatic const char * const ad5064_powerdown_modes[] = {
2298c2ecf20Sopenharmony_ci	"1kohm_to_gnd",
2308c2ecf20Sopenharmony_ci	"100kohm_to_gnd",
2318c2ecf20Sopenharmony_ci	"three_state",
2328c2ecf20Sopenharmony_ci};
2338c2ecf20Sopenharmony_ci
2348c2ecf20Sopenharmony_cistatic const char * const ltc2617_powerdown_modes[] = {
2358c2ecf20Sopenharmony_ci	"90kohm_to_gnd",
2368c2ecf20Sopenharmony_ci};
2378c2ecf20Sopenharmony_ci
2388c2ecf20Sopenharmony_cistatic int ad5064_get_powerdown_mode(struct iio_dev *indio_dev,
2398c2ecf20Sopenharmony_ci	const struct iio_chan_spec *chan)
2408c2ecf20Sopenharmony_ci{
2418c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
2428c2ecf20Sopenharmony_ci
2438c2ecf20Sopenharmony_ci	return st->pwr_down_mode[chan->channel] - 1;
2448c2ecf20Sopenharmony_ci}
2458c2ecf20Sopenharmony_ci
2468c2ecf20Sopenharmony_cistatic int ad5064_set_powerdown_mode(struct iio_dev *indio_dev,
2478c2ecf20Sopenharmony_ci	const struct iio_chan_spec *chan, unsigned int mode)
2488c2ecf20Sopenharmony_ci{
2498c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
2508c2ecf20Sopenharmony_ci	int ret;
2518c2ecf20Sopenharmony_ci
2528c2ecf20Sopenharmony_ci	mutex_lock(&st->lock);
2538c2ecf20Sopenharmony_ci	st->pwr_down_mode[chan->channel] = mode + 1;
2548c2ecf20Sopenharmony_ci
2558c2ecf20Sopenharmony_ci	ret = ad5064_sync_powerdown_mode(st, chan);
2568c2ecf20Sopenharmony_ci	mutex_unlock(&st->lock);
2578c2ecf20Sopenharmony_ci
2588c2ecf20Sopenharmony_ci	return ret;
2598c2ecf20Sopenharmony_ci}
2608c2ecf20Sopenharmony_ci
2618c2ecf20Sopenharmony_cistatic const struct iio_enum ad5064_powerdown_mode_enum = {
2628c2ecf20Sopenharmony_ci	.items = ad5064_powerdown_modes,
2638c2ecf20Sopenharmony_ci	.num_items = ARRAY_SIZE(ad5064_powerdown_modes),
2648c2ecf20Sopenharmony_ci	.get = ad5064_get_powerdown_mode,
2658c2ecf20Sopenharmony_ci	.set = ad5064_set_powerdown_mode,
2668c2ecf20Sopenharmony_ci};
2678c2ecf20Sopenharmony_ci
2688c2ecf20Sopenharmony_cistatic const struct iio_enum ltc2617_powerdown_mode_enum = {
2698c2ecf20Sopenharmony_ci	.items = ltc2617_powerdown_modes,
2708c2ecf20Sopenharmony_ci	.num_items = ARRAY_SIZE(ltc2617_powerdown_modes),
2718c2ecf20Sopenharmony_ci	.get = ad5064_get_powerdown_mode,
2728c2ecf20Sopenharmony_ci	.set = ad5064_set_powerdown_mode,
2738c2ecf20Sopenharmony_ci};
2748c2ecf20Sopenharmony_ci
2758c2ecf20Sopenharmony_cistatic ssize_t ad5064_read_dac_powerdown(struct iio_dev *indio_dev,
2768c2ecf20Sopenharmony_ci	uintptr_t private, const struct iio_chan_spec *chan, char *buf)
2778c2ecf20Sopenharmony_ci{
2788c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
2798c2ecf20Sopenharmony_ci
2808c2ecf20Sopenharmony_ci	return sprintf(buf, "%d\n", st->pwr_down[chan->channel]);
2818c2ecf20Sopenharmony_ci}
2828c2ecf20Sopenharmony_ci
2838c2ecf20Sopenharmony_cistatic ssize_t ad5064_write_dac_powerdown(struct iio_dev *indio_dev,
2848c2ecf20Sopenharmony_ci	 uintptr_t private, const struct iio_chan_spec *chan, const char *buf,
2858c2ecf20Sopenharmony_ci	 size_t len)
2868c2ecf20Sopenharmony_ci{
2878c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
2888c2ecf20Sopenharmony_ci	bool pwr_down;
2898c2ecf20Sopenharmony_ci	int ret;
2908c2ecf20Sopenharmony_ci
2918c2ecf20Sopenharmony_ci	ret = strtobool(buf, &pwr_down);
2928c2ecf20Sopenharmony_ci	if (ret)
2938c2ecf20Sopenharmony_ci		return ret;
2948c2ecf20Sopenharmony_ci
2958c2ecf20Sopenharmony_ci	mutex_lock(&st->lock);
2968c2ecf20Sopenharmony_ci	st->pwr_down[chan->channel] = pwr_down;
2978c2ecf20Sopenharmony_ci
2988c2ecf20Sopenharmony_ci	ret = ad5064_sync_powerdown_mode(st, chan);
2998c2ecf20Sopenharmony_ci	mutex_unlock(&st->lock);
3008c2ecf20Sopenharmony_ci	return ret ? ret : len;
3018c2ecf20Sopenharmony_ci}
3028c2ecf20Sopenharmony_ci
3038c2ecf20Sopenharmony_cistatic int ad5064_get_vref(struct ad5064_state *st,
3048c2ecf20Sopenharmony_ci	struct iio_chan_spec const *chan)
3058c2ecf20Sopenharmony_ci{
3068c2ecf20Sopenharmony_ci	unsigned int i;
3078c2ecf20Sopenharmony_ci
3088c2ecf20Sopenharmony_ci	if (st->use_internal_vref)
3098c2ecf20Sopenharmony_ci		return st->chip_info->internal_vref;
3108c2ecf20Sopenharmony_ci
3118c2ecf20Sopenharmony_ci	i = st->chip_info->shared_vref ? 0 : chan->channel;
3128c2ecf20Sopenharmony_ci	return regulator_get_voltage(st->vref_reg[i].consumer);
3138c2ecf20Sopenharmony_ci}
3148c2ecf20Sopenharmony_ci
3158c2ecf20Sopenharmony_cistatic int ad5064_read_raw(struct iio_dev *indio_dev,
3168c2ecf20Sopenharmony_ci			   struct iio_chan_spec const *chan,
3178c2ecf20Sopenharmony_ci			   int *val,
3188c2ecf20Sopenharmony_ci			   int *val2,
3198c2ecf20Sopenharmony_ci			   long m)
3208c2ecf20Sopenharmony_ci{
3218c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
3228c2ecf20Sopenharmony_ci	int scale_uv;
3238c2ecf20Sopenharmony_ci
3248c2ecf20Sopenharmony_ci	switch (m) {
3258c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
3268c2ecf20Sopenharmony_ci		*val = st->dac_cache[chan->channel];
3278c2ecf20Sopenharmony_ci		return IIO_VAL_INT;
3288c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
3298c2ecf20Sopenharmony_ci		scale_uv = ad5064_get_vref(st, chan);
3308c2ecf20Sopenharmony_ci		if (scale_uv < 0)
3318c2ecf20Sopenharmony_ci			return scale_uv;
3328c2ecf20Sopenharmony_ci
3338c2ecf20Sopenharmony_ci		*val = scale_uv / 1000;
3348c2ecf20Sopenharmony_ci		*val2 = chan->scan_type.realbits;
3358c2ecf20Sopenharmony_ci		return IIO_VAL_FRACTIONAL_LOG2;
3368c2ecf20Sopenharmony_ci	default:
3378c2ecf20Sopenharmony_ci		break;
3388c2ecf20Sopenharmony_ci	}
3398c2ecf20Sopenharmony_ci	return -EINVAL;
3408c2ecf20Sopenharmony_ci}
3418c2ecf20Sopenharmony_ci
3428c2ecf20Sopenharmony_cistatic int ad5064_write_raw(struct iio_dev *indio_dev,
3438c2ecf20Sopenharmony_ci	struct iio_chan_spec const *chan, int val, int val2, long mask)
3448c2ecf20Sopenharmony_ci{
3458c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
3468c2ecf20Sopenharmony_ci	int ret;
3478c2ecf20Sopenharmony_ci
3488c2ecf20Sopenharmony_ci	switch (mask) {
3498c2ecf20Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
3508c2ecf20Sopenharmony_ci		if (val >= (1 << chan->scan_type.realbits) || val < 0)
3518c2ecf20Sopenharmony_ci			return -EINVAL;
3528c2ecf20Sopenharmony_ci
3538c2ecf20Sopenharmony_ci		mutex_lock(&st->lock);
3548c2ecf20Sopenharmony_ci		ret = ad5064_write(st, AD5064_CMD_WRITE_INPUT_N_UPDATE_N,
3558c2ecf20Sopenharmony_ci				chan->address, val, chan->scan_type.shift);
3568c2ecf20Sopenharmony_ci		if (ret == 0)
3578c2ecf20Sopenharmony_ci			st->dac_cache[chan->channel] = val;
3588c2ecf20Sopenharmony_ci		mutex_unlock(&st->lock);
3598c2ecf20Sopenharmony_ci		break;
3608c2ecf20Sopenharmony_ci	default:
3618c2ecf20Sopenharmony_ci		ret = -EINVAL;
3628c2ecf20Sopenharmony_ci	}
3638c2ecf20Sopenharmony_ci
3648c2ecf20Sopenharmony_ci	return ret;
3658c2ecf20Sopenharmony_ci}
3668c2ecf20Sopenharmony_ci
3678c2ecf20Sopenharmony_cistatic const struct iio_info ad5064_info = {
3688c2ecf20Sopenharmony_ci	.read_raw = ad5064_read_raw,
3698c2ecf20Sopenharmony_ci	.write_raw = ad5064_write_raw,
3708c2ecf20Sopenharmony_ci};
3718c2ecf20Sopenharmony_ci
3728c2ecf20Sopenharmony_cistatic const struct iio_chan_spec_ext_info ad5064_ext_info[] = {
3738c2ecf20Sopenharmony_ci	{
3748c2ecf20Sopenharmony_ci		.name = "powerdown",
3758c2ecf20Sopenharmony_ci		.read = ad5064_read_dac_powerdown,
3768c2ecf20Sopenharmony_ci		.write = ad5064_write_dac_powerdown,
3778c2ecf20Sopenharmony_ci		.shared = IIO_SEPARATE,
3788c2ecf20Sopenharmony_ci	},
3798c2ecf20Sopenharmony_ci	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5064_powerdown_mode_enum),
3808c2ecf20Sopenharmony_ci	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5064_powerdown_mode_enum),
3818c2ecf20Sopenharmony_ci	{ },
3828c2ecf20Sopenharmony_ci};
3838c2ecf20Sopenharmony_ci
3848c2ecf20Sopenharmony_cistatic const struct iio_chan_spec_ext_info ltc2617_ext_info[] = {
3858c2ecf20Sopenharmony_ci	{
3868c2ecf20Sopenharmony_ci		.name = "powerdown",
3878c2ecf20Sopenharmony_ci		.read = ad5064_read_dac_powerdown,
3888c2ecf20Sopenharmony_ci		.write = ad5064_write_dac_powerdown,
3898c2ecf20Sopenharmony_ci		.shared = IIO_SEPARATE,
3908c2ecf20Sopenharmony_ci	},
3918c2ecf20Sopenharmony_ci	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ltc2617_powerdown_mode_enum),
3928c2ecf20Sopenharmony_ci	IIO_ENUM_AVAILABLE("powerdown_mode", &ltc2617_powerdown_mode_enum),
3938c2ecf20Sopenharmony_ci	{ },
3948c2ecf20Sopenharmony_ci};
3958c2ecf20Sopenharmony_ci
3968c2ecf20Sopenharmony_ci#define AD5064_CHANNEL(chan, addr, bits, _shift, _ext_info) {		\
3978c2ecf20Sopenharmony_ci	.type = IIO_VOLTAGE,					\
3988c2ecf20Sopenharmony_ci	.indexed = 1,						\
3998c2ecf20Sopenharmony_ci	.output = 1,						\
4008c2ecf20Sopenharmony_ci	.channel = (chan),					\
4018c2ecf20Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
4028c2ecf20Sopenharmony_ci	BIT(IIO_CHAN_INFO_SCALE),					\
4038c2ecf20Sopenharmony_ci	.address = addr,					\
4048c2ecf20Sopenharmony_ci	.scan_type = {						\
4058c2ecf20Sopenharmony_ci		.sign = 'u',					\
4068c2ecf20Sopenharmony_ci		.realbits = (bits),				\
4078c2ecf20Sopenharmony_ci		.storagebits = 16,				\
4088c2ecf20Sopenharmony_ci		.shift = (_shift),				\
4098c2ecf20Sopenharmony_ci	},							\
4108c2ecf20Sopenharmony_ci	.ext_info = (_ext_info),				\
4118c2ecf20Sopenharmony_ci}
4128c2ecf20Sopenharmony_ci
4138c2ecf20Sopenharmony_ci#define DECLARE_AD5064_CHANNELS(name, bits, shift, ext_info) \
4148c2ecf20Sopenharmony_ciconst struct iio_chan_spec name[] = { \
4158c2ecf20Sopenharmony_ci	AD5064_CHANNEL(0, 0, bits, shift, ext_info), \
4168c2ecf20Sopenharmony_ci	AD5064_CHANNEL(1, 1, bits, shift, ext_info), \
4178c2ecf20Sopenharmony_ci	AD5064_CHANNEL(2, 2, bits, shift, ext_info), \
4188c2ecf20Sopenharmony_ci	AD5064_CHANNEL(3, 3, bits, shift, ext_info), \
4198c2ecf20Sopenharmony_ci	AD5064_CHANNEL(4, 4, bits, shift, ext_info), \
4208c2ecf20Sopenharmony_ci	AD5064_CHANNEL(5, 5, bits, shift, ext_info), \
4218c2ecf20Sopenharmony_ci	AD5064_CHANNEL(6, 6, bits, shift, ext_info), \
4228c2ecf20Sopenharmony_ci	AD5064_CHANNEL(7, 7, bits, shift, ext_info), \
4238c2ecf20Sopenharmony_ci}
4248c2ecf20Sopenharmony_ci
4258c2ecf20Sopenharmony_ci#define DECLARE_AD5065_CHANNELS(name, bits, shift, ext_info) \
4268c2ecf20Sopenharmony_ciconst struct iio_chan_spec name[] = { \
4278c2ecf20Sopenharmony_ci	AD5064_CHANNEL(0, 0, bits, shift, ext_info), \
4288c2ecf20Sopenharmony_ci	AD5064_CHANNEL(1, 3, bits, shift, ext_info), \
4298c2ecf20Sopenharmony_ci}
4308c2ecf20Sopenharmony_ci
4318c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5024_channels, 12, 8, ad5064_ext_info);
4328c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5044_channels, 14, 6, ad5064_ext_info);
4338c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5064_channels, 16, 4, ad5064_ext_info);
4348c2ecf20Sopenharmony_ci
4358c2ecf20Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5025_channels, 12, 8, ad5064_ext_info);
4368c2ecf20Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5045_channels, 14, 6, ad5064_ext_info);
4378c2ecf20Sopenharmony_cistatic DECLARE_AD5065_CHANNELS(ad5065_channels, 16, 4, ad5064_ext_info);
4388c2ecf20Sopenharmony_ci
4398c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5629_channels, 12, 4, ad5064_ext_info);
4408c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5645_channels, 14, 2, ad5064_ext_info);
4418c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ad5669_channels, 16, 0, ad5064_ext_info);
4428c2ecf20Sopenharmony_ci
4438c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2607_channels, 16, 0, ltc2617_ext_info);
4448c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2617_channels, 14, 2, ltc2617_ext_info);
4458c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2627_channels, 12, 4, ltc2617_ext_info);
4468c2ecf20Sopenharmony_ci#define ltc2631_12_channels ltc2627_channels
4478c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2631_10_channels, 10, 6, ltc2617_ext_info);
4488c2ecf20Sopenharmony_cistatic DECLARE_AD5064_CHANNELS(ltc2631_8_channels, 8, 8, ltc2617_ext_info);
4498c2ecf20Sopenharmony_ci
4508c2ecf20Sopenharmony_ci#define LTC2631_INFO(vref, pchannels, nchannels)	\
4518c2ecf20Sopenharmony_ci	{						\
4528c2ecf20Sopenharmony_ci		.shared_vref = true,			\
4538c2ecf20Sopenharmony_ci		.internal_vref = vref,			\
4548c2ecf20Sopenharmony_ci		.channels = pchannels,			\
4558c2ecf20Sopenharmony_ci		.num_channels = nchannels,		\
4568c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,	\
4578c2ecf20Sopenharmony_ci	}
4588c2ecf20Sopenharmony_ci
4598c2ecf20Sopenharmony_ci
4608c2ecf20Sopenharmony_cistatic const struct ad5064_chip_info ad5064_chip_info_tbl[] = {
4618c2ecf20Sopenharmony_ci	[ID_AD5024] = {
4628c2ecf20Sopenharmony_ci		.shared_vref = false,
4638c2ecf20Sopenharmony_ci		.channels = ad5024_channels,
4648c2ecf20Sopenharmony_ci		.num_channels = 4,
4658c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
4668c2ecf20Sopenharmony_ci	},
4678c2ecf20Sopenharmony_ci	[ID_AD5025] = {
4688c2ecf20Sopenharmony_ci		.shared_vref = false,
4698c2ecf20Sopenharmony_ci		.channels = ad5025_channels,
4708c2ecf20Sopenharmony_ci		.num_channels = 2,
4718c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
4728c2ecf20Sopenharmony_ci	},
4738c2ecf20Sopenharmony_ci	[ID_AD5044] = {
4748c2ecf20Sopenharmony_ci		.shared_vref = false,
4758c2ecf20Sopenharmony_ci		.channels = ad5044_channels,
4768c2ecf20Sopenharmony_ci		.num_channels = 4,
4778c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
4788c2ecf20Sopenharmony_ci	},
4798c2ecf20Sopenharmony_ci	[ID_AD5045] = {
4808c2ecf20Sopenharmony_ci		.shared_vref = false,
4818c2ecf20Sopenharmony_ci		.channels = ad5045_channels,
4828c2ecf20Sopenharmony_ci		.num_channels = 2,
4838c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
4848c2ecf20Sopenharmony_ci	},
4858c2ecf20Sopenharmony_ci	[ID_AD5064] = {
4868c2ecf20Sopenharmony_ci		.shared_vref = false,
4878c2ecf20Sopenharmony_ci		.channels = ad5064_channels,
4888c2ecf20Sopenharmony_ci		.num_channels = 4,
4898c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
4908c2ecf20Sopenharmony_ci	},
4918c2ecf20Sopenharmony_ci	[ID_AD5064_1] = {
4928c2ecf20Sopenharmony_ci		.shared_vref = true,
4938c2ecf20Sopenharmony_ci		.channels = ad5064_channels,
4948c2ecf20Sopenharmony_ci		.num_channels = 4,
4958c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
4968c2ecf20Sopenharmony_ci	},
4978c2ecf20Sopenharmony_ci	[ID_AD5065] = {
4988c2ecf20Sopenharmony_ci		.shared_vref = false,
4998c2ecf20Sopenharmony_ci		.channels = ad5065_channels,
5008c2ecf20Sopenharmony_ci		.num_channels = 2,
5018c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
5028c2ecf20Sopenharmony_ci	},
5038c2ecf20Sopenharmony_ci	[ID_AD5625] = {
5048c2ecf20Sopenharmony_ci		.shared_vref = true,
5058c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5068c2ecf20Sopenharmony_ci		.num_channels = 4,
5078c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5088c2ecf20Sopenharmony_ci	},
5098c2ecf20Sopenharmony_ci	[ID_AD5625R_1V25] = {
5108c2ecf20Sopenharmony_ci		.shared_vref = true,
5118c2ecf20Sopenharmony_ci		.internal_vref = 1250000,
5128c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5138c2ecf20Sopenharmony_ci		.num_channels = 4,
5148c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5158c2ecf20Sopenharmony_ci	},
5168c2ecf20Sopenharmony_ci	[ID_AD5625R_2V5] = {
5178c2ecf20Sopenharmony_ci		.shared_vref = true,
5188c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
5198c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5208c2ecf20Sopenharmony_ci		.num_channels = 4,
5218c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5228c2ecf20Sopenharmony_ci	},
5238c2ecf20Sopenharmony_ci	[ID_AD5627] = {
5248c2ecf20Sopenharmony_ci		.shared_vref = true,
5258c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5268c2ecf20Sopenharmony_ci		.num_channels = 2,
5278c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5288c2ecf20Sopenharmony_ci	},
5298c2ecf20Sopenharmony_ci	[ID_AD5627R_1V25] = {
5308c2ecf20Sopenharmony_ci		.shared_vref = true,
5318c2ecf20Sopenharmony_ci		.internal_vref = 1250000,
5328c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5338c2ecf20Sopenharmony_ci		.num_channels = 2,
5348c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5358c2ecf20Sopenharmony_ci	},
5368c2ecf20Sopenharmony_ci	[ID_AD5627R_2V5] = {
5378c2ecf20Sopenharmony_ci		.shared_vref = true,
5388c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
5398c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5408c2ecf20Sopenharmony_ci		.num_channels = 2,
5418c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5428c2ecf20Sopenharmony_ci	},
5438c2ecf20Sopenharmony_ci	[ID_AD5628_1] = {
5448c2ecf20Sopenharmony_ci		.shared_vref = true,
5458c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
5468c2ecf20Sopenharmony_ci		.channels = ad5024_channels,
5478c2ecf20Sopenharmony_ci		.num_channels = 8,
5488c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
5498c2ecf20Sopenharmony_ci	},
5508c2ecf20Sopenharmony_ci	[ID_AD5628_2] = {
5518c2ecf20Sopenharmony_ci		.shared_vref = true,
5528c2ecf20Sopenharmony_ci		.internal_vref = 5000000,
5538c2ecf20Sopenharmony_ci		.channels = ad5024_channels,
5548c2ecf20Sopenharmony_ci		.num_channels = 8,
5558c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
5568c2ecf20Sopenharmony_ci	},
5578c2ecf20Sopenharmony_ci	[ID_AD5629_1] = {
5588c2ecf20Sopenharmony_ci		.shared_vref = true,
5598c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
5608c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5618c2ecf20Sopenharmony_ci		.num_channels = 8,
5628c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
5638c2ecf20Sopenharmony_ci	},
5648c2ecf20Sopenharmony_ci	[ID_AD5629_2] = {
5658c2ecf20Sopenharmony_ci		.shared_vref = true,
5668c2ecf20Sopenharmony_ci		.internal_vref = 5000000,
5678c2ecf20Sopenharmony_ci		.channels = ad5629_channels,
5688c2ecf20Sopenharmony_ci		.num_channels = 8,
5698c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
5708c2ecf20Sopenharmony_ci	},
5718c2ecf20Sopenharmony_ci	[ID_AD5645R_1V25] = {
5728c2ecf20Sopenharmony_ci		.shared_vref = true,
5738c2ecf20Sopenharmony_ci		.internal_vref = 1250000,
5748c2ecf20Sopenharmony_ci		.channels = ad5645_channels,
5758c2ecf20Sopenharmony_ci		.num_channels = 4,
5768c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5778c2ecf20Sopenharmony_ci	},
5788c2ecf20Sopenharmony_ci	[ID_AD5645R_2V5] = {
5798c2ecf20Sopenharmony_ci		.shared_vref = true,
5808c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
5818c2ecf20Sopenharmony_ci		.channels = ad5645_channels,
5828c2ecf20Sopenharmony_ci		.num_channels = 4,
5838c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5848c2ecf20Sopenharmony_ci	},
5858c2ecf20Sopenharmony_ci	[ID_AD5647R_1V25] = {
5868c2ecf20Sopenharmony_ci		.shared_vref = true,
5878c2ecf20Sopenharmony_ci		.internal_vref = 1250000,
5888c2ecf20Sopenharmony_ci		.channels = ad5645_channels,
5898c2ecf20Sopenharmony_ci		.num_channels = 2,
5908c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5918c2ecf20Sopenharmony_ci	},
5928c2ecf20Sopenharmony_ci	[ID_AD5647R_2V5] = {
5938c2ecf20Sopenharmony_ci		.shared_vref = true,
5948c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
5958c2ecf20Sopenharmony_ci		.channels = ad5645_channels,
5968c2ecf20Sopenharmony_ci		.num_channels = 2,
5978c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
5988c2ecf20Sopenharmony_ci	},
5998c2ecf20Sopenharmony_ci	[ID_AD5648_1] = {
6008c2ecf20Sopenharmony_ci		.shared_vref = true,
6018c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
6028c2ecf20Sopenharmony_ci		.channels = ad5044_channels,
6038c2ecf20Sopenharmony_ci		.num_channels = 8,
6048c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6058c2ecf20Sopenharmony_ci	},
6068c2ecf20Sopenharmony_ci	[ID_AD5648_2] = {
6078c2ecf20Sopenharmony_ci		.shared_vref = true,
6088c2ecf20Sopenharmony_ci		.internal_vref = 5000000,
6098c2ecf20Sopenharmony_ci		.channels = ad5044_channels,
6108c2ecf20Sopenharmony_ci		.num_channels = 8,
6118c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6128c2ecf20Sopenharmony_ci	},
6138c2ecf20Sopenharmony_ci	[ID_AD5665] = {
6148c2ecf20Sopenharmony_ci		.shared_vref = true,
6158c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6168c2ecf20Sopenharmony_ci		.num_channels = 4,
6178c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
6188c2ecf20Sopenharmony_ci	},
6198c2ecf20Sopenharmony_ci	[ID_AD5665R_1V25] = {
6208c2ecf20Sopenharmony_ci		.shared_vref = true,
6218c2ecf20Sopenharmony_ci		.internal_vref = 1250000,
6228c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6238c2ecf20Sopenharmony_ci		.num_channels = 4,
6248c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
6258c2ecf20Sopenharmony_ci	},
6268c2ecf20Sopenharmony_ci	[ID_AD5665R_2V5] = {
6278c2ecf20Sopenharmony_ci		.shared_vref = true,
6288c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
6298c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6308c2ecf20Sopenharmony_ci		.num_channels = 4,
6318c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
6328c2ecf20Sopenharmony_ci	},
6338c2ecf20Sopenharmony_ci	[ID_AD5666_1] = {
6348c2ecf20Sopenharmony_ci		.shared_vref = true,
6358c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
6368c2ecf20Sopenharmony_ci		.channels = ad5064_channels,
6378c2ecf20Sopenharmony_ci		.num_channels = 4,
6388c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6398c2ecf20Sopenharmony_ci	},
6408c2ecf20Sopenharmony_ci	[ID_AD5666_2] = {
6418c2ecf20Sopenharmony_ci		.shared_vref = true,
6428c2ecf20Sopenharmony_ci		.internal_vref = 5000000,
6438c2ecf20Sopenharmony_ci		.channels = ad5064_channels,
6448c2ecf20Sopenharmony_ci		.num_channels = 4,
6458c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6468c2ecf20Sopenharmony_ci	},
6478c2ecf20Sopenharmony_ci	[ID_AD5667] = {
6488c2ecf20Sopenharmony_ci		.shared_vref = true,
6498c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6508c2ecf20Sopenharmony_ci		.num_channels = 2,
6518c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
6528c2ecf20Sopenharmony_ci	},
6538c2ecf20Sopenharmony_ci	[ID_AD5667R_1V25] = {
6548c2ecf20Sopenharmony_ci		.shared_vref = true,
6558c2ecf20Sopenharmony_ci		.internal_vref = 1250000,
6568c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6578c2ecf20Sopenharmony_ci		.num_channels = 2,
6588c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
6598c2ecf20Sopenharmony_ci	},
6608c2ecf20Sopenharmony_ci	[ID_AD5667R_2V5] = {
6618c2ecf20Sopenharmony_ci		.shared_vref = true,
6628c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
6638c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6648c2ecf20Sopenharmony_ci		.num_channels = 2,
6658c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI2
6668c2ecf20Sopenharmony_ci	},
6678c2ecf20Sopenharmony_ci	[ID_AD5668_1] = {
6688c2ecf20Sopenharmony_ci		.shared_vref = true,
6698c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
6708c2ecf20Sopenharmony_ci		.channels = ad5064_channels,
6718c2ecf20Sopenharmony_ci		.num_channels = 8,
6728c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6738c2ecf20Sopenharmony_ci	},
6748c2ecf20Sopenharmony_ci	[ID_AD5668_2] = {
6758c2ecf20Sopenharmony_ci		.shared_vref = true,
6768c2ecf20Sopenharmony_ci		.internal_vref = 5000000,
6778c2ecf20Sopenharmony_ci		.channels = ad5064_channels,
6788c2ecf20Sopenharmony_ci		.num_channels = 8,
6798c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6808c2ecf20Sopenharmony_ci	},
6818c2ecf20Sopenharmony_ci	[ID_AD5669_1] = {
6828c2ecf20Sopenharmony_ci		.shared_vref = true,
6838c2ecf20Sopenharmony_ci		.internal_vref = 2500000,
6848c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6858c2ecf20Sopenharmony_ci		.num_channels = 8,
6868c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6878c2ecf20Sopenharmony_ci	},
6888c2ecf20Sopenharmony_ci	[ID_AD5669_2] = {
6898c2ecf20Sopenharmony_ci		.shared_vref = true,
6908c2ecf20Sopenharmony_ci		.internal_vref = 5000000,
6918c2ecf20Sopenharmony_ci		.channels = ad5669_channels,
6928c2ecf20Sopenharmony_ci		.num_channels = 8,
6938c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_ADI,
6948c2ecf20Sopenharmony_ci	},
6958c2ecf20Sopenharmony_ci	[ID_LTC2606] = {
6968c2ecf20Sopenharmony_ci		.shared_vref = true,
6978c2ecf20Sopenharmony_ci		.internal_vref = 0,
6988c2ecf20Sopenharmony_ci		.channels = ltc2607_channels,
6998c2ecf20Sopenharmony_ci		.num_channels = 1,
7008c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7018c2ecf20Sopenharmony_ci	},
7028c2ecf20Sopenharmony_ci	[ID_LTC2607] = {
7038c2ecf20Sopenharmony_ci		.shared_vref = true,
7048c2ecf20Sopenharmony_ci		.internal_vref = 0,
7058c2ecf20Sopenharmony_ci		.channels = ltc2607_channels,
7068c2ecf20Sopenharmony_ci		.num_channels = 2,
7078c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7088c2ecf20Sopenharmony_ci	},
7098c2ecf20Sopenharmony_ci	[ID_LTC2609] = {
7108c2ecf20Sopenharmony_ci		.shared_vref = false,
7118c2ecf20Sopenharmony_ci		.internal_vref = 0,
7128c2ecf20Sopenharmony_ci		.channels = ltc2607_channels,
7138c2ecf20Sopenharmony_ci		.num_channels = 4,
7148c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7158c2ecf20Sopenharmony_ci	},
7168c2ecf20Sopenharmony_ci	[ID_LTC2616] = {
7178c2ecf20Sopenharmony_ci		.shared_vref = true,
7188c2ecf20Sopenharmony_ci		.internal_vref = 0,
7198c2ecf20Sopenharmony_ci		.channels = ltc2617_channels,
7208c2ecf20Sopenharmony_ci		.num_channels = 1,
7218c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7228c2ecf20Sopenharmony_ci	},
7238c2ecf20Sopenharmony_ci	[ID_LTC2617] = {
7248c2ecf20Sopenharmony_ci		.shared_vref = true,
7258c2ecf20Sopenharmony_ci		.internal_vref = 0,
7268c2ecf20Sopenharmony_ci		.channels = ltc2617_channels,
7278c2ecf20Sopenharmony_ci		.num_channels = 2,
7288c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7298c2ecf20Sopenharmony_ci	},
7308c2ecf20Sopenharmony_ci	[ID_LTC2619] = {
7318c2ecf20Sopenharmony_ci		.shared_vref = false,
7328c2ecf20Sopenharmony_ci		.internal_vref = 0,
7338c2ecf20Sopenharmony_ci		.channels = ltc2617_channels,
7348c2ecf20Sopenharmony_ci		.num_channels = 4,
7358c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7368c2ecf20Sopenharmony_ci	},
7378c2ecf20Sopenharmony_ci	[ID_LTC2626] = {
7388c2ecf20Sopenharmony_ci		.shared_vref = true,
7398c2ecf20Sopenharmony_ci		.internal_vref = 0,
7408c2ecf20Sopenharmony_ci		.channels = ltc2627_channels,
7418c2ecf20Sopenharmony_ci		.num_channels = 1,
7428c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7438c2ecf20Sopenharmony_ci	},
7448c2ecf20Sopenharmony_ci	[ID_LTC2627] = {
7458c2ecf20Sopenharmony_ci		.shared_vref = true,
7468c2ecf20Sopenharmony_ci		.internal_vref = 0,
7478c2ecf20Sopenharmony_ci		.channels = ltc2627_channels,
7488c2ecf20Sopenharmony_ci		.num_channels = 2,
7498c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7508c2ecf20Sopenharmony_ci	},
7518c2ecf20Sopenharmony_ci	[ID_LTC2629] = {
7528c2ecf20Sopenharmony_ci		.shared_vref = false,
7538c2ecf20Sopenharmony_ci		.internal_vref = 0,
7548c2ecf20Sopenharmony_ci		.channels = ltc2627_channels,
7558c2ecf20Sopenharmony_ci		.num_channels = 4,
7568c2ecf20Sopenharmony_ci		.regmap_type = AD5064_REGMAP_LTC,
7578c2ecf20Sopenharmony_ci	},
7588c2ecf20Sopenharmony_ci	[ID_LTC2631_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 1),
7598c2ecf20Sopenharmony_ci	[ID_LTC2631_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 1),
7608c2ecf20Sopenharmony_ci	[ID_LTC2631_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 1),
7618c2ecf20Sopenharmony_ci	[ID_LTC2631_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 1),
7628c2ecf20Sopenharmony_ci	[ID_LTC2631_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 1),
7638c2ecf20Sopenharmony_ci	[ID_LTC2631_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 1),
7648c2ecf20Sopenharmony_ci	[ID_LTC2633_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 2),
7658c2ecf20Sopenharmony_ci	[ID_LTC2633_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 2),
7668c2ecf20Sopenharmony_ci	[ID_LTC2633_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 2),
7678c2ecf20Sopenharmony_ci	[ID_LTC2633_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 2),
7688c2ecf20Sopenharmony_ci	[ID_LTC2633_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 2),
7698c2ecf20Sopenharmony_ci	[ID_LTC2633_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 2),
7708c2ecf20Sopenharmony_ci	[ID_LTC2635_L12] = LTC2631_INFO(2500000, ltc2631_12_channels, 4),
7718c2ecf20Sopenharmony_ci	[ID_LTC2635_H12] = LTC2631_INFO(4096000, ltc2631_12_channels, 4),
7728c2ecf20Sopenharmony_ci	[ID_LTC2635_L10] = LTC2631_INFO(2500000, ltc2631_10_channels, 4),
7738c2ecf20Sopenharmony_ci	[ID_LTC2635_H10] = LTC2631_INFO(4096000, ltc2631_10_channels, 4),
7748c2ecf20Sopenharmony_ci	[ID_LTC2635_L8] = LTC2631_INFO(2500000, ltc2631_8_channels, 4),
7758c2ecf20Sopenharmony_ci	[ID_LTC2635_H8] = LTC2631_INFO(4096000, ltc2631_8_channels, 4),
7768c2ecf20Sopenharmony_ci};
7778c2ecf20Sopenharmony_ci
7788c2ecf20Sopenharmony_cistatic inline unsigned int ad5064_num_vref(struct ad5064_state *st)
7798c2ecf20Sopenharmony_ci{
7808c2ecf20Sopenharmony_ci	return st->chip_info->shared_vref ? 1 : st->chip_info->num_channels;
7818c2ecf20Sopenharmony_ci}
7828c2ecf20Sopenharmony_ci
7838c2ecf20Sopenharmony_cistatic const char * const ad5064_vref_names[] = {
7848c2ecf20Sopenharmony_ci	"vrefA",
7858c2ecf20Sopenharmony_ci	"vrefB",
7868c2ecf20Sopenharmony_ci	"vrefC",
7878c2ecf20Sopenharmony_ci	"vrefD",
7888c2ecf20Sopenharmony_ci};
7898c2ecf20Sopenharmony_ci
7908c2ecf20Sopenharmony_cistatic const char *ad5064_vref_name(struct ad5064_state *st,
7918c2ecf20Sopenharmony_ci	unsigned int vref)
7928c2ecf20Sopenharmony_ci{
7938c2ecf20Sopenharmony_ci	return st->chip_info->shared_vref ? "vref" : ad5064_vref_names[vref];
7948c2ecf20Sopenharmony_ci}
7958c2ecf20Sopenharmony_ci
7968c2ecf20Sopenharmony_cistatic int ad5064_set_config(struct ad5064_state *st, unsigned int val)
7978c2ecf20Sopenharmony_ci{
7988c2ecf20Sopenharmony_ci	unsigned int cmd;
7998c2ecf20Sopenharmony_ci
8008c2ecf20Sopenharmony_ci	switch (st->chip_info->regmap_type) {
8018c2ecf20Sopenharmony_ci	case AD5064_REGMAP_ADI2:
8028c2ecf20Sopenharmony_ci		cmd = AD5064_CMD_CONFIG_V2;
8038c2ecf20Sopenharmony_ci		break;
8048c2ecf20Sopenharmony_ci	default:
8058c2ecf20Sopenharmony_ci		cmd = AD5064_CMD_CONFIG;
8068c2ecf20Sopenharmony_ci		break;
8078c2ecf20Sopenharmony_ci	}
8088c2ecf20Sopenharmony_ci
8098c2ecf20Sopenharmony_ci	return ad5064_write(st, cmd, 0, val, 0);
8108c2ecf20Sopenharmony_ci}
8118c2ecf20Sopenharmony_ci
8128c2ecf20Sopenharmony_cistatic int ad5064_request_vref(struct ad5064_state *st, struct device *dev)
8138c2ecf20Sopenharmony_ci{
8148c2ecf20Sopenharmony_ci	unsigned int i;
8158c2ecf20Sopenharmony_ci	int ret;
8168c2ecf20Sopenharmony_ci
8178c2ecf20Sopenharmony_ci	for (i = 0; i < ad5064_num_vref(st); ++i)
8188c2ecf20Sopenharmony_ci		st->vref_reg[i].supply = ad5064_vref_name(st, i);
8198c2ecf20Sopenharmony_ci
8208c2ecf20Sopenharmony_ci	if (!st->chip_info->internal_vref)
8218c2ecf20Sopenharmony_ci		return devm_regulator_bulk_get(dev, ad5064_num_vref(st),
8228c2ecf20Sopenharmony_ci					       st->vref_reg);
8238c2ecf20Sopenharmony_ci
8248c2ecf20Sopenharmony_ci	/*
8258c2ecf20Sopenharmony_ci	 * This assumes that when the regulator has an internal VREF
8268c2ecf20Sopenharmony_ci	 * there is only one external VREF connection, which is
8278c2ecf20Sopenharmony_ci	 * currently the case for all supported devices.
8288c2ecf20Sopenharmony_ci	 */
8298c2ecf20Sopenharmony_ci	st->vref_reg[0].consumer = devm_regulator_get_optional(dev, "vref");
8308c2ecf20Sopenharmony_ci	if (!IS_ERR(st->vref_reg[0].consumer))
8318c2ecf20Sopenharmony_ci		return 0;
8328c2ecf20Sopenharmony_ci
8338c2ecf20Sopenharmony_ci	ret = PTR_ERR(st->vref_reg[0].consumer);
8348c2ecf20Sopenharmony_ci	if (ret != -ENODEV)
8358c2ecf20Sopenharmony_ci		return ret;
8368c2ecf20Sopenharmony_ci
8378c2ecf20Sopenharmony_ci	/* If no external regulator was supplied use the internal VREF */
8388c2ecf20Sopenharmony_ci	st->use_internal_vref = true;
8398c2ecf20Sopenharmony_ci	ret = ad5064_set_config(st, AD5064_CONFIG_INT_VREF_ENABLE);
8408c2ecf20Sopenharmony_ci	if (ret)
8418c2ecf20Sopenharmony_ci		dev_err(dev, "Failed to enable internal vref: %d\n", ret);
8428c2ecf20Sopenharmony_ci
8438c2ecf20Sopenharmony_ci	return ret;
8448c2ecf20Sopenharmony_ci}
8458c2ecf20Sopenharmony_ci
8468c2ecf20Sopenharmony_cistatic int ad5064_probe(struct device *dev, enum ad5064_type type,
8478c2ecf20Sopenharmony_ci			const char *name, ad5064_write_func write)
8488c2ecf20Sopenharmony_ci{
8498c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev;
8508c2ecf20Sopenharmony_ci	struct ad5064_state *st;
8518c2ecf20Sopenharmony_ci	unsigned int midscale;
8528c2ecf20Sopenharmony_ci	unsigned int i;
8538c2ecf20Sopenharmony_ci	int ret;
8548c2ecf20Sopenharmony_ci
8558c2ecf20Sopenharmony_ci	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
8568c2ecf20Sopenharmony_ci	if (indio_dev == NULL)
8578c2ecf20Sopenharmony_ci		return  -ENOMEM;
8588c2ecf20Sopenharmony_ci
8598c2ecf20Sopenharmony_ci	st = iio_priv(indio_dev);
8608c2ecf20Sopenharmony_ci	mutex_init(&st->lock);
8618c2ecf20Sopenharmony_ci	dev_set_drvdata(dev, indio_dev);
8628c2ecf20Sopenharmony_ci
8638c2ecf20Sopenharmony_ci	st->chip_info = &ad5064_chip_info_tbl[type];
8648c2ecf20Sopenharmony_ci	st->dev = dev;
8658c2ecf20Sopenharmony_ci	st->write = write;
8668c2ecf20Sopenharmony_ci
8678c2ecf20Sopenharmony_ci	ret = ad5064_request_vref(st, dev);
8688c2ecf20Sopenharmony_ci	if (ret)
8698c2ecf20Sopenharmony_ci		return ret;
8708c2ecf20Sopenharmony_ci
8718c2ecf20Sopenharmony_ci	if (!st->use_internal_vref) {
8728c2ecf20Sopenharmony_ci		ret = regulator_bulk_enable(ad5064_num_vref(st), st->vref_reg);
8738c2ecf20Sopenharmony_ci		if (ret)
8748c2ecf20Sopenharmony_ci			return ret;
8758c2ecf20Sopenharmony_ci	}
8768c2ecf20Sopenharmony_ci
8778c2ecf20Sopenharmony_ci	indio_dev->name = name;
8788c2ecf20Sopenharmony_ci	indio_dev->info = &ad5064_info;
8798c2ecf20Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
8808c2ecf20Sopenharmony_ci	indio_dev->channels = st->chip_info->channels;
8818c2ecf20Sopenharmony_ci	indio_dev->num_channels = st->chip_info->num_channels;
8828c2ecf20Sopenharmony_ci
8838c2ecf20Sopenharmony_ci	midscale = (1 << indio_dev->channels[0].scan_type.realbits) /  2;
8848c2ecf20Sopenharmony_ci
8858c2ecf20Sopenharmony_ci	for (i = 0; i < st->chip_info->num_channels; ++i) {
8868c2ecf20Sopenharmony_ci		st->pwr_down_mode[i] = AD5064_LDAC_PWRDN_1K;
8878c2ecf20Sopenharmony_ci		st->dac_cache[i] = midscale;
8888c2ecf20Sopenharmony_ci	}
8898c2ecf20Sopenharmony_ci
8908c2ecf20Sopenharmony_ci	ret = iio_device_register(indio_dev);
8918c2ecf20Sopenharmony_ci	if (ret)
8928c2ecf20Sopenharmony_ci		goto error_disable_reg;
8938c2ecf20Sopenharmony_ci
8948c2ecf20Sopenharmony_ci	return 0;
8958c2ecf20Sopenharmony_ci
8968c2ecf20Sopenharmony_cierror_disable_reg:
8978c2ecf20Sopenharmony_ci	if (!st->use_internal_vref)
8988c2ecf20Sopenharmony_ci		regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg);
8998c2ecf20Sopenharmony_ci
9008c2ecf20Sopenharmony_ci	return ret;
9018c2ecf20Sopenharmony_ci}
9028c2ecf20Sopenharmony_ci
9038c2ecf20Sopenharmony_cistatic int ad5064_remove(struct device *dev)
9048c2ecf20Sopenharmony_ci{
9058c2ecf20Sopenharmony_ci	struct iio_dev *indio_dev = dev_get_drvdata(dev);
9068c2ecf20Sopenharmony_ci	struct ad5064_state *st = iio_priv(indio_dev);
9078c2ecf20Sopenharmony_ci
9088c2ecf20Sopenharmony_ci	iio_device_unregister(indio_dev);
9098c2ecf20Sopenharmony_ci
9108c2ecf20Sopenharmony_ci	if (!st->use_internal_vref)
9118c2ecf20Sopenharmony_ci		regulator_bulk_disable(ad5064_num_vref(st), st->vref_reg);
9128c2ecf20Sopenharmony_ci
9138c2ecf20Sopenharmony_ci	return 0;
9148c2ecf20Sopenharmony_ci}
9158c2ecf20Sopenharmony_ci
9168c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_SPI_MASTER)
9178c2ecf20Sopenharmony_ci
9188c2ecf20Sopenharmony_cistatic int ad5064_spi_write(struct ad5064_state *st, unsigned int cmd,
9198c2ecf20Sopenharmony_ci	unsigned int addr, unsigned int val)
9208c2ecf20Sopenharmony_ci{
9218c2ecf20Sopenharmony_ci	struct spi_device *spi = to_spi_device(st->dev);
9228c2ecf20Sopenharmony_ci
9238c2ecf20Sopenharmony_ci	st->data.spi = cpu_to_be32(AD5064_CMD(cmd) | AD5064_ADDR(addr) | val);
9248c2ecf20Sopenharmony_ci	return spi_write(spi, &st->data.spi, sizeof(st->data.spi));
9258c2ecf20Sopenharmony_ci}
9268c2ecf20Sopenharmony_ci
9278c2ecf20Sopenharmony_cistatic int ad5064_spi_probe(struct spi_device *spi)
9288c2ecf20Sopenharmony_ci{
9298c2ecf20Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
9308c2ecf20Sopenharmony_ci
9318c2ecf20Sopenharmony_ci	return ad5064_probe(&spi->dev, id->driver_data, id->name,
9328c2ecf20Sopenharmony_ci				ad5064_spi_write);
9338c2ecf20Sopenharmony_ci}
9348c2ecf20Sopenharmony_ci
9358c2ecf20Sopenharmony_cistatic int ad5064_spi_remove(struct spi_device *spi)
9368c2ecf20Sopenharmony_ci{
9378c2ecf20Sopenharmony_ci	return ad5064_remove(&spi->dev);
9388c2ecf20Sopenharmony_ci}
9398c2ecf20Sopenharmony_ci
9408c2ecf20Sopenharmony_cistatic const struct spi_device_id ad5064_spi_ids[] = {
9418c2ecf20Sopenharmony_ci	{"ad5024", ID_AD5024},
9428c2ecf20Sopenharmony_ci	{"ad5025", ID_AD5025},
9438c2ecf20Sopenharmony_ci	{"ad5044", ID_AD5044},
9448c2ecf20Sopenharmony_ci	{"ad5045", ID_AD5045},
9458c2ecf20Sopenharmony_ci	{"ad5064", ID_AD5064},
9468c2ecf20Sopenharmony_ci	{"ad5064-1", ID_AD5064_1},
9478c2ecf20Sopenharmony_ci	{"ad5065", ID_AD5065},
9488c2ecf20Sopenharmony_ci	{"ad5628-1", ID_AD5628_1},
9498c2ecf20Sopenharmony_ci	{"ad5628-2", ID_AD5628_2},
9508c2ecf20Sopenharmony_ci	{"ad5648-1", ID_AD5648_1},
9518c2ecf20Sopenharmony_ci	{"ad5648-2", ID_AD5648_2},
9528c2ecf20Sopenharmony_ci	{"ad5666-1", ID_AD5666_1},
9538c2ecf20Sopenharmony_ci	{"ad5666-2", ID_AD5666_2},
9548c2ecf20Sopenharmony_ci	{"ad5668-1", ID_AD5668_1},
9558c2ecf20Sopenharmony_ci	{"ad5668-2", ID_AD5668_2},
9568c2ecf20Sopenharmony_ci	{"ad5668-3", ID_AD5668_2}, /* similar enough to ad5668-2 */
9578c2ecf20Sopenharmony_ci	{}
9588c2ecf20Sopenharmony_ci};
9598c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5064_spi_ids);
9608c2ecf20Sopenharmony_ci
9618c2ecf20Sopenharmony_cistatic struct spi_driver ad5064_spi_driver = {
9628c2ecf20Sopenharmony_ci	.driver = {
9638c2ecf20Sopenharmony_ci		   .name = "ad5064",
9648c2ecf20Sopenharmony_ci	},
9658c2ecf20Sopenharmony_ci	.probe = ad5064_spi_probe,
9668c2ecf20Sopenharmony_ci	.remove = ad5064_spi_remove,
9678c2ecf20Sopenharmony_ci	.id_table = ad5064_spi_ids,
9688c2ecf20Sopenharmony_ci};
9698c2ecf20Sopenharmony_ci
9708c2ecf20Sopenharmony_cistatic int __init ad5064_spi_register_driver(void)
9718c2ecf20Sopenharmony_ci{
9728c2ecf20Sopenharmony_ci	return spi_register_driver(&ad5064_spi_driver);
9738c2ecf20Sopenharmony_ci}
9748c2ecf20Sopenharmony_ci
9758c2ecf20Sopenharmony_cistatic void ad5064_spi_unregister_driver(void)
9768c2ecf20Sopenharmony_ci{
9778c2ecf20Sopenharmony_ci	spi_unregister_driver(&ad5064_spi_driver);
9788c2ecf20Sopenharmony_ci}
9798c2ecf20Sopenharmony_ci
9808c2ecf20Sopenharmony_ci#else
9818c2ecf20Sopenharmony_ci
9828c2ecf20Sopenharmony_cistatic inline int ad5064_spi_register_driver(void) { return 0; }
9838c2ecf20Sopenharmony_cistatic inline void ad5064_spi_unregister_driver(void) { }
9848c2ecf20Sopenharmony_ci
9858c2ecf20Sopenharmony_ci#endif
9868c2ecf20Sopenharmony_ci
9878c2ecf20Sopenharmony_ci#if IS_ENABLED(CONFIG_I2C)
9888c2ecf20Sopenharmony_ci
9898c2ecf20Sopenharmony_cistatic int ad5064_i2c_write(struct ad5064_state *st, unsigned int cmd,
9908c2ecf20Sopenharmony_ci	unsigned int addr, unsigned int val)
9918c2ecf20Sopenharmony_ci{
9928c2ecf20Sopenharmony_ci	struct i2c_client *i2c = to_i2c_client(st->dev);
9938c2ecf20Sopenharmony_ci	unsigned int cmd_shift;
9948c2ecf20Sopenharmony_ci	int ret;
9958c2ecf20Sopenharmony_ci
9968c2ecf20Sopenharmony_ci	switch (st->chip_info->regmap_type) {
9978c2ecf20Sopenharmony_ci	case AD5064_REGMAP_ADI2:
9988c2ecf20Sopenharmony_ci		cmd_shift = 3;
9998c2ecf20Sopenharmony_ci		break;
10008c2ecf20Sopenharmony_ci	default:
10018c2ecf20Sopenharmony_ci		cmd_shift = 4;
10028c2ecf20Sopenharmony_ci		break;
10038c2ecf20Sopenharmony_ci	}
10048c2ecf20Sopenharmony_ci
10058c2ecf20Sopenharmony_ci	st->data.i2c[0] = (cmd << cmd_shift) | addr;
10068c2ecf20Sopenharmony_ci	put_unaligned_be16(val, &st->data.i2c[1]);
10078c2ecf20Sopenharmony_ci
10088c2ecf20Sopenharmony_ci	ret = i2c_master_send(i2c, st->data.i2c, 3);
10098c2ecf20Sopenharmony_ci	if (ret < 0)
10108c2ecf20Sopenharmony_ci		return ret;
10118c2ecf20Sopenharmony_ci
10128c2ecf20Sopenharmony_ci	return 0;
10138c2ecf20Sopenharmony_ci}
10148c2ecf20Sopenharmony_ci
10158c2ecf20Sopenharmony_cistatic int ad5064_i2c_probe(struct i2c_client *i2c,
10168c2ecf20Sopenharmony_ci	const struct i2c_device_id *id)
10178c2ecf20Sopenharmony_ci{
10188c2ecf20Sopenharmony_ci	return ad5064_probe(&i2c->dev, id->driver_data, id->name,
10198c2ecf20Sopenharmony_ci						ad5064_i2c_write);
10208c2ecf20Sopenharmony_ci}
10218c2ecf20Sopenharmony_ci
10228c2ecf20Sopenharmony_cistatic int ad5064_i2c_remove(struct i2c_client *i2c)
10238c2ecf20Sopenharmony_ci{
10248c2ecf20Sopenharmony_ci	return ad5064_remove(&i2c->dev);
10258c2ecf20Sopenharmony_ci}
10268c2ecf20Sopenharmony_ci
10278c2ecf20Sopenharmony_cistatic const struct i2c_device_id ad5064_i2c_ids[] = {
10288c2ecf20Sopenharmony_ci	{"ad5625", ID_AD5625 },
10298c2ecf20Sopenharmony_ci	{"ad5625r-1v25", ID_AD5625R_1V25 },
10308c2ecf20Sopenharmony_ci	{"ad5625r-2v5", ID_AD5625R_2V5 },
10318c2ecf20Sopenharmony_ci	{"ad5627", ID_AD5627 },
10328c2ecf20Sopenharmony_ci	{"ad5627r-1v25", ID_AD5627R_1V25 },
10338c2ecf20Sopenharmony_ci	{"ad5627r-2v5", ID_AD5627R_2V5 },
10348c2ecf20Sopenharmony_ci	{"ad5629-1", ID_AD5629_1},
10358c2ecf20Sopenharmony_ci	{"ad5629-2", ID_AD5629_2},
10368c2ecf20Sopenharmony_ci	{"ad5629-3", ID_AD5629_2}, /* similar enough to ad5629-2 */
10378c2ecf20Sopenharmony_ci	{"ad5645r-1v25", ID_AD5645R_1V25 },
10388c2ecf20Sopenharmony_ci	{"ad5645r-2v5", ID_AD5645R_2V5 },
10398c2ecf20Sopenharmony_ci	{"ad5665", ID_AD5665 },
10408c2ecf20Sopenharmony_ci	{"ad5665r-1v25", ID_AD5665R_1V25 },
10418c2ecf20Sopenharmony_ci	{"ad5665r-2v5", ID_AD5665R_2V5 },
10428c2ecf20Sopenharmony_ci	{"ad5667", ID_AD5667 },
10438c2ecf20Sopenharmony_ci	{"ad5667r-1v25", ID_AD5667R_1V25 },
10448c2ecf20Sopenharmony_ci	{"ad5667r-2v5", ID_AD5667R_2V5 },
10458c2ecf20Sopenharmony_ci	{"ad5669-1", ID_AD5669_1},
10468c2ecf20Sopenharmony_ci	{"ad5669-2", ID_AD5669_2},
10478c2ecf20Sopenharmony_ci	{"ad5669-3", ID_AD5669_2}, /* similar enough to ad5669-2 */
10488c2ecf20Sopenharmony_ci	{"ltc2606", ID_LTC2606},
10498c2ecf20Sopenharmony_ci	{"ltc2607", ID_LTC2607},
10508c2ecf20Sopenharmony_ci	{"ltc2609", ID_LTC2609},
10518c2ecf20Sopenharmony_ci	{"ltc2616", ID_LTC2616},
10528c2ecf20Sopenharmony_ci	{"ltc2617", ID_LTC2617},
10538c2ecf20Sopenharmony_ci	{"ltc2619", ID_LTC2619},
10548c2ecf20Sopenharmony_ci	{"ltc2626", ID_LTC2626},
10558c2ecf20Sopenharmony_ci	{"ltc2627", ID_LTC2627},
10568c2ecf20Sopenharmony_ci	{"ltc2629", ID_LTC2629},
10578c2ecf20Sopenharmony_ci	{"ltc2631-l12", ID_LTC2631_L12},
10588c2ecf20Sopenharmony_ci	{"ltc2631-h12", ID_LTC2631_H12},
10598c2ecf20Sopenharmony_ci	{"ltc2631-l10", ID_LTC2631_L10},
10608c2ecf20Sopenharmony_ci	{"ltc2631-h10", ID_LTC2631_H10},
10618c2ecf20Sopenharmony_ci	{"ltc2631-l8", ID_LTC2631_L8},
10628c2ecf20Sopenharmony_ci	{"ltc2631-h8", ID_LTC2631_H8},
10638c2ecf20Sopenharmony_ci	{"ltc2633-l12", ID_LTC2633_L12},
10648c2ecf20Sopenharmony_ci	{"ltc2633-h12", ID_LTC2633_H12},
10658c2ecf20Sopenharmony_ci	{"ltc2633-l10", ID_LTC2633_L10},
10668c2ecf20Sopenharmony_ci	{"ltc2633-h10", ID_LTC2633_H10},
10678c2ecf20Sopenharmony_ci	{"ltc2633-l8", ID_LTC2633_L8},
10688c2ecf20Sopenharmony_ci	{"ltc2633-h8", ID_LTC2633_H8},
10698c2ecf20Sopenharmony_ci	{"ltc2635-l12", ID_LTC2635_L12},
10708c2ecf20Sopenharmony_ci	{"ltc2635-h12", ID_LTC2635_H12},
10718c2ecf20Sopenharmony_ci	{"ltc2635-l10", ID_LTC2635_L10},
10728c2ecf20Sopenharmony_ci	{"ltc2635-h10", ID_LTC2635_H10},
10738c2ecf20Sopenharmony_ci	{"ltc2635-l8", ID_LTC2635_L8},
10748c2ecf20Sopenharmony_ci	{"ltc2635-h8", ID_LTC2635_H8},
10758c2ecf20Sopenharmony_ci	{}
10768c2ecf20Sopenharmony_ci};
10778c2ecf20Sopenharmony_ciMODULE_DEVICE_TABLE(i2c, ad5064_i2c_ids);
10788c2ecf20Sopenharmony_ci
10798c2ecf20Sopenharmony_cistatic struct i2c_driver ad5064_i2c_driver = {
10808c2ecf20Sopenharmony_ci	.driver = {
10818c2ecf20Sopenharmony_ci		   .name = "ad5064",
10828c2ecf20Sopenharmony_ci	},
10838c2ecf20Sopenharmony_ci	.probe = ad5064_i2c_probe,
10848c2ecf20Sopenharmony_ci	.remove = ad5064_i2c_remove,
10858c2ecf20Sopenharmony_ci	.id_table = ad5064_i2c_ids,
10868c2ecf20Sopenharmony_ci};
10878c2ecf20Sopenharmony_ci
10888c2ecf20Sopenharmony_cistatic int __init ad5064_i2c_register_driver(void)
10898c2ecf20Sopenharmony_ci{
10908c2ecf20Sopenharmony_ci	return i2c_add_driver(&ad5064_i2c_driver);
10918c2ecf20Sopenharmony_ci}
10928c2ecf20Sopenharmony_ci
10938c2ecf20Sopenharmony_cistatic void __exit ad5064_i2c_unregister_driver(void)
10948c2ecf20Sopenharmony_ci{
10958c2ecf20Sopenharmony_ci	i2c_del_driver(&ad5064_i2c_driver);
10968c2ecf20Sopenharmony_ci}
10978c2ecf20Sopenharmony_ci
10988c2ecf20Sopenharmony_ci#else
10998c2ecf20Sopenharmony_ci
11008c2ecf20Sopenharmony_cistatic inline int ad5064_i2c_register_driver(void) { return 0; }
11018c2ecf20Sopenharmony_cistatic inline void ad5064_i2c_unregister_driver(void) { }
11028c2ecf20Sopenharmony_ci
11038c2ecf20Sopenharmony_ci#endif
11048c2ecf20Sopenharmony_ci
11058c2ecf20Sopenharmony_cistatic int __init ad5064_init(void)
11068c2ecf20Sopenharmony_ci{
11078c2ecf20Sopenharmony_ci	int ret;
11088c2ecf20Sopenharmony_ci
11098c2ecf20Sopenharmony_ci	ret = ad5064_spi_register_driver();
11108c2ecf20Sopenharmony_ci	if (ret)
11118c2ecf20Sopenharmony_ci		return ret;
11128c2ecf20Sopenharmony_ci
11138c2ecf20Sopenharmony_ci	ret = ad5064_i2c_register_driver();
11148c2ecf20Sopenharmony_ci	if (ret) {
11158c2ecf20Sopenharmony_ci		ad5064_spi_unregister_driver();
11168c2ecf20Sopenharmony_ci		return ret;
11178c2ecf20Sopenharmony_ci	}
11188c2ecf20Sopenharmony_ci
11198c2ecf20Sopenharmony_ci	return 0;
11208c2ecf20Sopenharmony_ci}
11218c2ecf20Sopenharmony_cimodule_init(ad5064_init);
11228c2ecf20Sopenharmony_ci
11238c2ecf20Sopenharmony_cistatic void __exit ad5064_exit(void)
11248c2ecf20Sopenharmony_ci{
11258c2ecf20Sopenharmony_ci	ad5064_i2c_unregister_driver();
11268c2ecf20Sopenharmony_ci	ad5064_spi_unregister_driver();
11278c2ecf20Sopenharmony_ci}
11288c2ecf20Sopenharmony_cimodule_exit(ad5064_exit);
11298c2ecf20Sopenharmony_ci
11308c2ecf20Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
11318c2ecf20Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5024 and similar multi-channel DACs");
11328c2ecf20Sopenharmony_ciMODULE_LICENSE("GPL v2");
1133