xref: /openbmc/linux/drivers/iio/dac/ad5446.c (revision 80503b23)
180503b23SThomas Gleixner // SPDX-License-Identifier: GPL-2.0-or-later
2dbdc025bSLars-Peter Clausen /*
3dbdc025bSLars-Peter Clausen  * AD5446 SPI DAC driver
4dbdc025bSLars-Peter Clausen  *
5dbdc025bSLars-Peter Clausen  * Copyright 2010 Analog Devices Inc.
6dbdc025bSLars-Peter Clausen  */
7dbdc025bSLars-Peter Clausen 
8dbdc025bSLars-Peter Clausen #include <linux/interrupt.h>
9dbdc025bSLars-Peter Clausen #include <linux/workqueue.h>
10dbdc025bSLars-Peter Clausen #include <linux/device.h>
11dbdc025bSLars-Peter Clausen #include <linux/kernel.h>
12dbdc025bSLars-Peter Clausen #include <linux/slab.h>
13dbdc025bSLars-Peter Clausen #include <linux/sysfs.h>
14dbdc025bSLars-Peter Clausen #include <linux/list.h>
15dbdc025bSLars-Peter Clausen #include <linux/spi/spi.h>
163ec36a2cSJean-Francois Dagenais #include <linux/i2c.h>
17dbdc025bSLars-Peter Clausen #include <linux/regulator/consumer.h>
18dbdc025bSLars-Peter Clausen #include <linux/err.h>
19dbdc025bSLars-Peter Clausen #include <linux/module.h>
20dbdc025bSLars-Peter Clausen 
21dbdc025bSLars-Peter Clausen #include <linux/iio/iio.h>
22dbdc025bSLars-Peter Clausen #include <linux/iio/sysfs.h>
23dbdc025bSLars-Peter Clausen 
242e15c903SJean-Francois Dagenais #define MODE_PWRDWN_1k		0x1
252e15c903SJean-Francois Dagenais #define MODE_PWRDWN_100k	0x2
262e15c903SJean-Francois Dagenais #define MODE_PWRDWN_TRISTATE	0x3
272e15c903SJean-Francois Dagenais 
282e15c903SJean-Francois Dagenais /**
292e15c903SJean-Francois Dagenais  * struct ad5446_state - driver instance specific data
302e15c903SJean-Francois Dagenais  * @spi:		spi_device
312e15c903SJean-Francois Dagenais  * @chip_info:		chip model specific constants, available modes etc
322e15c903SJean-Francois Dagenais  * @reg:		supply regulator
332e15c903SJean-Francois Dagenais  * @vref_mv:		actual reference voltage used
342e15c903SJean-Francois Dagenais  */
352e15c903SJean-Francois Dagenais 
362e15c903SJean-Francois Dagenais struct ad5446_state {
372e15c903SJean-Francois Dagenais 	struct device		*dev;
382e15c903SJean-Francois Dagenais 	const struct ad5446_chip_info	*chip_info;
392e15c903SJean-Francois Dagenais 	struct regulator		*reg;
402e15c903SJean-Francois Dagenais 	unsigned short			vref_mv;
412e15c903SJean-Francois Dagenais 	unsigned			cached_val;
422e15c903SJean-Francois Dagenais 	unsigned			pwr_down_mode;
432e15c903SJean-Francois Dagenais 	unsigned			pwr_down;
442e15c903SJean-Francois Dagenais };
452e15c903SJean-Francois Dagenais 
462e15c903SJean-Francois Dagenais /**
472e15c903SJean-Francois Dagenais  * struct ad5446_chip_info - chip specific information
482e15c903SJean-Francois Dagenais  * @channel:		channel spec for the DAC
492e15c903SJean-Francois Dagenais  * @int_vref_mv:	AD5620/40/60: the internal reference voltage
502e15c903SJean-Francois Dagenais  * @write:		chip specific helper function to write to the register
512e15c903SJean-Francois Dagenais  */
522e15c903SJean-Francois Dagenais 
532e15c903SJean-Francois Dagenais struct ad5446_chip_info {
542e15c903SJean-Francois Dagenais 	struct iio_chan_spec	channel;
552e15c903SJean-Francois Dagenais 	u16			int_vref_mv;
562e15c903SJean-Francois Dagenais 	int			(*write)(struct ad5446_state *st, unsigned val);
572e15c903SJean-Francois Dagenais };
58dbdc025bSLars-Peter Clausen 
59dbdc025bSLars-Peter Clausen static const char * const ad5446_powerdown_modes[] = {
60dbdc025bSLars-Peter Clausen 	"1kohm_to_gnd", "100kohm_to_gnd", "three_state"
61dbdc025bSLars-Peter Clausen };
62dbdc025bSLars-Peter Clausen 
63dbdc025bSLars-Peter Clausen static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev,
64dbdc025bSLars-Peter Clausen 	const struct iio_chan_spec *chan, unsigned int mode)
65dbdc025bSLars-Peter Clausen {
66dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
67dbdc025bSLars-Peter Clausen 
68dbdc025bSLars-Peter Clausen 	st->pwr_down_mode = mode + 1;
69dbdc025bSLars-Peter Clausen 
70dbdc025bSLars-Peter Clausen 	return 0;
71dbdc025bSLars-Peter Clausen }
72dbdc025bSLars-Peter Clausen 
73dbdc025bSLars-Peter Clausen static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev,
74dbdc025bSLars-Peter Clausen 	const struct iio_chan_spec *chan)
75dbdc025bSLars-Peter Clausen {
76dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
77dbdc025bSLars-Peter Clausen 
78dbdc025bSLars-Peter Clausen 	return st->pwr_down_mode - 1;
79dbdc025bSLars-Peter Clausen }
80dbdc025bSLars-Peter Clausen 
81dbdc025bSLars-Peter Clausen static const struct iio_enum ad5446_powerdown_mode_enum = {
82dbdc025bSLars-Peter Clausen 	.items = ad5446_powerdown_modes,
83dbdc025bSLars-Peter Clausen 	.num_items = ARRAY_SIZE(ad5446_powerdown_modes),
84dbdc025bSLars-Peter Clausen 	.get = ad5446_get_powerdown_mode,
85dbdc025bSLars-Peter Clausen 	.set = ad5446_set_powerdown_mode,
86dbdc025bSLars-Peter Clausen };
87dbdc025bSLars-Peter Clausen 
88dbdc025bSLars-Peter Clausen static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
89dbdc025bSLars-Peter Clausen 					   uintptr_t private,
90dbdc025bSLars-Peter Clausen 					   const struct iio_chan_spec *chan,
91dbdc025bSLars-Peter Clausen 					   char *buf)
92dbdc025bSLars-Peter Clausen {
93dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
94dbdc025bSLars-Peter Clausen 
95dbdc025bSLars-Peter Clausen 	return sprintf(buf, "%d\n", st->pwr_down);
96dbdc025bSLars-Peter Clausen }
97dbdc025bSLars-Peter Clausen 
98dbdc025bSLars-Peter Clausen static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
99dbdc025bSLars-Peter Clausen 					    uintptr_t private,
100dbdc025bSLars-Peter Clausen 					    const struct iio_chan_spec *chan,
101dbdc025bSLars-Peter Clausen 					    const char *buf, size_t len)
102dbdc025bSLars-Peter Clausen {
103dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
104dbdc025bSLars-Peter Clausen 	unsigned int shift;
105dbdc025bSLars-Peter Clausen 	unsigned int val;
106dbdc025bSLars-Peter Clausen 	bool powerdown;
107dbdc025bSLars-Peter Clausen 	int ret;
108dbdc025bSLars-Peter Clausen 
109dbdc025bSLars-Peter Clausen 	ret = strtobool(buf, &powerdown);
110dbdc025bSLars-Peter Clausen 	if (ret)
111dbdc025bSLars-Peter Clausen 		return ret;
112dbdc025bSLars-Peter Clausen 
113dbdc025bSLars-Peter Clausen 	mutex_lock(&indio_dev->mlock);
114dbdc025bSLars-Peter Clausen 	st->pwr_down = powerdown;
115dbdc025bSLars-Peter Clausen 
116dbdc025bSLars-Peter Clausen 	if (st->pwr_down) {
117dbdc025bSLars-Peter Clausen 		shift = chan->scan_type.realbits + chan->scan_type.shift;
118dbdc025bSLars-Peter Clausen 		val = st->pwr_down_mode << shift;
119dbdc025bSLars-Peter Clausen 	} else {
120dbdc025bSLars-Peter Clausen 		val = st->cached_val;
121dbdc025bSLars-Peter Clausen 	}
122dbdc025bSLars-Peter Clausen 
123dbdc025bSLars-Peter Clausen 	ret = st->chip_info->write(st, val);
124dbdc025bSLars-Peter Clausen 	mutex_unlock(&indio_dev->mlock);
125dbdc025bSLars-Peter Clausen 
126dbdc025bSLars-Peter Clausen 	return ret ? ret : len;
127dbdc025bSLars-Peter Clausen }
128dbdc025bSLars-Peter Clausen 
1293ec36a2cSJean-Francois Dagenais static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
130dbdc025bSLars-Peter Clausen 	{
131dbdc025bSLars-Peter Clausen 		.name = "powerdown",
132dbdc025bSLars-Peter Clausen 		.read = ad5446_read_dac_powerdown,
133dbdc025bSLars-Peter Clausen 		.write = ad5446_write_dac_powerdown,
1343704432fSJonathan Cameron 		.shared = IIO_SEPARATE,
135dbdc025bSLars-Peter Clausen 	},
1363704432fSJonathan Cameron 	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
137dbdc025bSLars-Peter Clausen 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5446_powerdown_mode_enum),
138dbdc025bSLars-Peter Clausen 	{ },
139dbdc025bSLars-Peter Clausen };
140dbdc025bSLars-Peter Clausen 
141e3019c21SJonathan Cameron #define _AD5446_CHANNEL(bits, storage, _shift, ext) { \
142dbdc025bSLars-Peter Clausen 	.type = IIO_VOLTAGE, \
143dbdc025bSLars-Peter Clausen 	.indexed = 1, \
144dbdc025bSLars-Peter Clausen 	.output = 1, \
145dbdc025bSLars-Peter Clausen 	.channel = 0, \
1462f6a4a44SJonathan Cameron 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
1472f6a4a44SJonathan Cameron 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
148e3019c21SJonathan Cameron 	.scan_type = { \
149e3019c21SJonathan Cameron 		.sign = 'u', \
150e3019c21SJonathan Cameron 		.realbits = (bits), \
151e3019c21SJonathan Cameron 		.storagebits = (storage), \
152e3019c21SJonathan Cameron 		.shift = (_shift), \
153e3019c21SJonathan Cameron 		}, \
154dbdc025bSLars-Peter Clausen 	.ext_info = (ext), \
155dbdc025bSLars-Peter Clausen }
156dbdc025bSLars-Peter Clausen 
157dbdc025bSLars-Peter Clausen #define AD5446_CHANNEL(bits, storage, shift) \
158dbdc025bSLars-Peter Clausen 	_AD5446_CHANNEL(bits, storage, shift, NULL)
159dbdc025bSLars-Peter Clausen 
160dbdc025bSLars-Peter Clausen #define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
1613ec36a2cSJean-Francois Dagenais 	_AD5446_CHANNEL(bits, storage, shift, ad5446_ext_info_powerdown)
162dbdc025bSLars-Peter Clausen 
1633ec36a2cSJean-Francois Dagenais static int ad5446_read_raw(struct iio_dev *indio_dev,
1643ec36a2cSJean-Francois Dagenais 			   struct iio_chan_spec const *chan,
1653ec36a2cSJean-Francois Dagenais 			   int *val,
1663ec36a2cSJean-Francois Dagenais 			   int *val2,
1673ec36a2cSJean-Francois Dagenais 			   long m)
1683ec36a2cSJean-Francois Dagenais {
1693ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st = iio_priv(indio_dev);
1703ec36a2cSJean-Francois Dagenais 
1713ec36a2cSJean-Francois Dagenais 	switch (m) {
1723ec36a2cSJean-Francois Dagenais 	case IIO_CHAN_INFO_RAW:
1733ec36a2cSJean-Francois Dagenais 		*val = st->cached_val;
1743ec36a2cSJean-Francois Dagenais 		return IIO_VAL_INT;
1753ec36a2cSJean-Francois Dagenais 	case IIO_CHAN_INFO_SCALE:
1760a99b601SLars-Peter Clausen 		*val = st->vref_mv;
1770a99b601SLars-Peter Clausen 		*val2 = chan->scan_type.realbits;
1780a99b601SLars-Peter Clausen 		return IIO_VAL_FRACTIONAL_LOG2;
1793ec36a2cSJean-Francois Dagenais 	}
1803ec36a2cSJean-Francois Dagenais 	return -EINVAL;
1813ec36a2cSJean-Francois Dagenais }
1823ec36a2cSJean-Francois Dagenais 
1833ec36a2cSJean-Francois Dagenais static int ad5446_write_raw(struct iio_dev *indio_dev,
1843ec36a2cSJean-Francois Dagenais 			       struct iio_chan_spec const *chan,
1853ec36a2cSJean-Francois Dagenais 			       int val,
1863ec36a2cSJean-Francois Dagenais 			       int val2,
1873ec36a2cSJean-Francois Dagenais 			       long mask)
1883ec36a2cSJean-Francois Dagenais {
1893ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st = iio_priv(indio_dev);
1903ec36a2cSJean-Francois Dagenais 	int ret = 0;
1913ec36a2cSJean-Francois Dagenais 
1923ec36a2cSJean-Francois Dagenais 	switch (mask) {
1933ec36a2cSJean-Francois Dagenais 	case IIO_CHAN_INFO_RAW:
1943ec36a2cSJean-Francois Dagenais 		if (val >= (1 << chan->scan_type.realbits) || val < 0)
1953ec36a2cSJean-Francois Dagenais 			return -EINVAL;
1963ec36a2cSJean-Francois Dagenais 
1973ec36a2cSJean-Francois Dagenais 		val <<= chan->scan_type.shift;
1983ec36a2cSJean-Francois Dagenais 		mutex_lock(&indio_dev->mlock);
1993ec36a2cSJean-Francois Dagenais 		st->cached_val = val;
2003ec36a2cSJean-Francois Dagenais 		if (!st->pwr_down)
2013ec36a2cSJean-Francois Dagenais 			ret = st->chip_info->write(st, val);
2023ec36a2cSJean-Francois Dagenais 		mutex_unlock(&indio_dev->mlock);
2033ec36a2cSJean-Francois Dagenais 		break;
2043ec36a2cSJean-Francois Dagenais 	default:
2053ec36a2cSJean-Francois Dagenais 		ret = -EINVAL;
2063ec36a2cSJean-Francois Dagenais 	}
2073ec36a2cSJean-Francois Dagenais 
2083ec36a2cSJean-Francois Dagenais 	return ret;
2093ec36a2cSJean-Francois Dagenais }
2103ec36a2cSJean-Francois Dagenais 
2113ec36a2cSJean-Francois Dagenais static const struct iio_info ad5446_info = {
2123ec36a2cSJean-Francois Dagenais 	.read_raw = ad5446_read_raw,
2133ec36a2cSJean-Francois Dagenais 	.write_raw = ad5446_write_raw,
2143ec36a2cSJean-Francois Dagenais };
2153ec36a2cSJean-Francois Dagenais 
216fc52692cSGreg Kroah-Hartman static int ad5446_probe(struct device *dev, const char *name,
2173ec36a2cSJean-Francois Dagenais 			const struct ad5446_chip_info *chip_info)
2183ec36a2cSJean-Francois Dagenais {
2193ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st;
2203ec36a2cSJean-Francois Dagenais 	struct iio_dev *indio_dev;
2213ec36a2cSJean-Francois Dagenais 	struct regulator *reg;
2223ec36a2cSJean-Francois Dagenais 	int ret, voltage_uv = 0;
2233ec36a2cSJean-Francois Dagenais 
224ba727295SSachin Kamat 	reg = devm_regulator_get(dev, "vcc");
2253ec36a2cSJean-Francois Dagenais 	if (!IS_ERR(reg)) {
2263ec36a2cSJean-Francois Dagenais 		ret = regulator_enable(reg);
2273ec36a2cSJean-Francois Dagenais 		if (ret)
228ba727295SSachin Kamat 			return ret;
2293ec36a2cSJean-Francois Dagenais 
23013e57ee2SAxel Lin 		ret = regulator_get_voltage(reg);
23113e57ee2SAxel Lin 		if (ret < 0)
23213e57ee2SAxel Lin 			goto error_disable_reg;
23313e57ee2SAxel Lin 
23413e57ee2SAxel Lin 		voltage_uv = ret;
2353ec36a2cSJean-Francois Dagenais 	}
2363ec36a2cSJean-Francois Dagenais 
237ba727295SSachin Kamat 	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
2383ec36a2cSJean-Francois Dagenais 	if (indio_dev == NULL) {
2393ec36a2cSJean-Francois Dagenais 		ret = -ENOMEM;
2403ec36a2cSJean-Francois Dagenais 		goto error_disable_reg;
2413ec36a2cSJean-Francois Dagenais 	}
2423ec36a2cSJean-Francois Dagenais 	st = iio_priv(indio_dev);
2433ec36a2cSJean-Francois Dagenais 	st->chip_info = chip_info;
2443ec36a2cSJean-Francois Dagenais 
2453ec36a2cSJean-Francois Dagenais 	dev_set_drvdata(dev, indio_dev);
2463ec36a2cSJean-Francois Dagenais 	st->reg = reg;
2473ec36a2cSJean-Francois Dagenais 	st->dev = dev;
2483ec36a2cSJean-Francois Dagenais 
2493ec36a2cSJean-Francois Dagenais 	/* Establish that the iio_dev is a child of the device */
2503ec36a2cSJean-Francois Dagenais 	indio_dev->dev.parent = dev;
2513ec36a2cSJean-Francois Dagenais 	indio_dev->name = name;
2523ec36a2cSJean-Francois Dagenais 	indio_dev->info = &ad5446_info;
2533ec36a2cSJean-Francois Dagenais 	indio_dev->modes = INDIO_DIRECT_MODE;
2543ec36a2cSJean-Francois Dagenais 	indio_dev->channels = &st->chip_info->channel;
2553ec36a2cSJean-Francois Dagenais 	indio_dev->num_channels = 1;
2563ec36a2cSJean-Francois Dagenais 
2573ec36a2cSJean-Francois Dagenais 	st->pwr_down_mode = MODE_PWRDWN_1k;
2583ec36a2cSJean-Francois Dagenais 
2593ec36a2cSJean-Francois Dagenais 	if (st->chip_info->int_vref_mv)
2603ec36a2cSJean-Francois Dagenais 		st->vref_mv = st->chip_info->int_vref_mv;
2613ec36a2cSJean-Francois Dagenais 	else if (voltage_uv)
2623ec36a2cSJean-Francois Dagenais 		st->vref_mv = voltage_uv / 1000;
2633ec36a2cSJean-Francois Dagenais 	else
2643ec36a2cSJean-Francois Dagenais 		dev_warn(dev, "reference voltage unspecified\n");
2653ec36a2cSJean-Francois Dagenais 
2663ec36a2cSJean-Francois Dagenais 	ret = iio_device_register(indio_dev);
2673ec36a2cSJean-Francois Dagenais 	if (ret)
268ba727295SSachin Kamat 		goto error_disable_reg;
2693ec36a2cSJean-Francois Dagenais 
2703ec36a2cSJean-Francois Dagenais 	return 0;
2713ec36a2cSJean-Francois Dagenais 
2723ec36a2cSJean-Francois Dagenais error_disable_reg:
2733ec36a2cSJean-Francois Dagenais 	if (!IS_ERR(reg))
2743ec36a2cSJean-Francois Dagenais 		regulator_disable(reg);
2753ec36a2cSJean-Francois Dagenais 	return ret;
2763ec36a2cSJean-Francois Dagenais }
2773ec36a2cSJean-Francois Dagenais 
2783ec36a2cSJean-Francois Dagenais static int ad5446_remove(struct device *dev)
2793ec36a2cSJean-Francois Dagenais {
2803ec36a2cSJean-Francois Dagenais 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
2813ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st = iio_priv(indio_dev);
2823ec36a2cSJean-Francois Dagenais 
2833ec36a2cSJean-Francois Dagenais 	iio_device_unregister(indio_dev);
284ba727295SSachin Kamat 	if (!IS_ERR(st->reg))
2853ec36a2cSJean-Francois Dagenais 		regulator_disable(st->reg);
2863ec36a2cSJean-Francois Dagenais 
2873ec36a2cSJean-Francois Dagenais 	return 0;
2883ec36a2cSJean-Francois Dagenais }
2893ec36a2cSJean-Francois Dagenais 
2903ec36a2cSJean-Francois Dagenais #if IS_ENABLED(CONFIG_SPI_MASTER)
2913ec36a2cSJean-Francois Dagenais 
2923ec36a2cSJean-Francois Dagenais static int ad5446_write(struct ad5446_state *st, unsigned val)
2933ec36a2cSJean-Francois Dagenais {
2943ec36a2cSJean-Francois Dagenais 	struct spi_device *spi = to_spi_device(st->dev);
2953ec36a2cSJean-Francois Dagenais 	__be16 data = cpu_to_be16(val);
2963ec36a2cSJean-Francois Dagenais 
2973ec36a2cSJean-Francois Dagenais 	return spi_write(spi, &data, sizeof(data));
2983ec36a2cSJean-Francois Dagenais }
2993ec36a2cSJean-Francois Dagenais 
3003ec36a2cSJean-Francois Dagenais static int ad5660_write(struct ad5446_state *st, unsigned val)
3013ec36a2cSJean-Francois Dagenais {
3023ec36a2cSJean-Francois Dagenais 	struct spi_device *spi = to_spi_device(st->dev);
3033ec36a2cSJean-Francois Dagenais 	uint8_t data[3];
3043ec36a2cSJean-Francois Dagenais 
3053ec36a2cSJean-Francois Dagenais 	data[0] = (val >> 16) & 0xFF;
3063ec36a2cSJean-Francois Dagenais 	data[1] = (val >> 8) & 0xFF;
3073ec36a2cSJean-Francois Dagenais 	data[2] = val & 0xFF;
3083ec36a2cSJean-Francois Dagenais 
3093ec36a2cSJean-Francois Dagenais 	return spi_write(spi, data, sizeof(data));
3103ec36a2cSJean-Francois Dagenais }
3113ec36a2cSJean-Francois Dagenais 
3123ec36a2cSJean-Francois Dagenais /**
3133ec36a2cSJean-Francois Dagenais  * ad5446_supported_spi_device_ids:
3143ec36a2cSJean-Francois Dagenais  * The AD5620/40/60 parts are available in different fixed internal reference
3153ec36a2cSJean-Francois Dagenais  * voltage options. The actual part numbers may look differently
3163ec36a2cSJean-Francois Dagenais  * (and a bit cryptic), however this style is used to make clear which
3173ec36a2cSJean-Francois Dagenais  * parts are supported here.
3183ec36a2cSJean-Francois Dagenais  */
3193ec36a2cSJean-Francois Dagenais enum ad5446_supported_spi_device_ids {
3202fafbce2SLars-Peter Clausen 	ID_AD5300,
3212fafbce2SLars-Peter Clausen 	ID_AD5310,
3222fafbce2SLars-Peter Clausen 	ID_AD5320,
3233ec36a2cSJean-Francois Dagenais 	ID_AD5444,
3243ec36a2cSJean-Francois Dagenais 	ID_AD5446,
3253ec36a2cSJean-Francois Dagenais 	ID_AD5450,
3263ec36a2cSJean-Francois Dagenais 	ID_AD5451,
3273ec36a2cSJean-Francois Dagenais 	ID_AD5541A,
3283ec36a2cSJean-Francois Dagenais 	ID_AD5512A,
3293ec36a2cSJean-Francois Dagenais 	ID_AD5553,
3303ec36a2cSJean-Francois Dagenais 	ID_AD5601,
3313ec36a2cSJean-Francois Dagenais 	ID_AD5611,
3323ec36a2cSJean-Francois Dagenais 	ID_AD5621,
3334fa2a9e4SAida Mynzhasova 	ID_AD5641,
3343ec36a2cSJean-Francois Dagenais 	ID_AD5620_2500,
3353ec36a2cSJean-Francois Dagenais 	ID_AD5620_1250,
3363ec36a2cSJean-Francois Dagenais 	ID_AD5640_2500,
3373ec36a2cSJean-Francois Dagenais 	ID_AD5640_1250,
3383ec36a2cSJean-Francois Dagenais 	ID_AD5660_2500,
3393ec36a2cSJean-Francois Dagenais 	ID_AD5660_1250,
3403ec36a2cSJean-Francois Dagenais 	ID_AD5662,
3413ec36a2cSJean-Francois Dagenais };
3423ec36a2cSJean-Francois Dagenais 
3433ec36a2cSJean-Francois Dagenais static const struct ad5446_chip_info ad5446_spi_chip_info[] = {
3442fafbce2SLars-Peter Clausen 	[ID_AD5300] = {
3452fafbce2SLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
3462fafbce2SLars-Peter Clausen 		.write = ad5446_write,
3472fafbce2SLars-Peter Clausen 	},
3482fafbce2SLars-Peter Clausen 	[ID_AD5310] = {
3492fafbce2SLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
3502fafbce2SLars-Peter Clausen 		.write = ad5446_write,
3512fafbce2SLars-Peter Clausen 	},
3522fafbce2SLars-Peter Clausen 	[ID_AD5320] = {
3532fafbce2SLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
3542fafbce2SLars-Peter Clausen 		.write = ad5446_write,
3552fafbce2SLars-Peter Clausen 	},
356dbdc025bSLars-Peter Clausen 	[ID_AD5444] = {
357dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(12, 16, 2),
358dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
359dbdc025bSLars-Peter Clausen 	},
360dbdc025bSLars-Peter Clausen 	[ID_AD5446] = {
361dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(14, 16, 0),
362dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
363dbdc025bSLars-Peter Clausen 	},
364779c0c46SLars-Peter Clausen 	[ID_AD5450] = {
365779c0c46SLars-Peter Clausen 		.channel = AD5446_CHANNEL(8, 16, 6),
366779c0c46SLars-Peter Clausen 		.write = ad5446_write,
367779c0c46SLars-Peter Clausen 	},
368779c0c46SLars-Peter Clausen 	[ID_AD5451] = {
369779c0c46SLars-Peter Clausen 		.channel = AD5446_CHANNEL(10, 16, 4),
370779c0c46SLars-Peter Clausen 		.write = ad5446_write,
371779c0c46SLars-Peter Clausen 	},
372dbdc025bSLars-Peter Clausen 	[ID_AD5541A] = {
373dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(16, 16, 0),
374dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
375dbdc025bSLars-Peter Clausen 	},
376dbdc025bSLars-Peter Clausen 	[ID_AD5512A] = {
377dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(12, 16, 4),
378dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
379dbdc025bSLars-Peter Clausen 	},
380dbdc025bSLars-Peter Clausen 	[ID_AD5553] = {
381dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(14, 16, 0),
382dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
383dbdc025bSLars-Peter Clausen 	},
384dbdc025bSLars-Peter Clausen 	[ID_AD5601] = {
385dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
386dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
387dbdc025bSLars-Peter Clausen 	},
388dbdc025bSLars-Peter Clausen 	[ID_AD5611] = {
389dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
390dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
391dbdc025bSLars-Peter Clausen 	},
392dbdc025bSLars-Peter Clausen 	[ID_AD5621] = {
393dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
394dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
395dbdc025bSLars-Peter Clausen 	},
3964fa2a9e4SAida Mynzhasova 	[ID_AD5641] = {
3974fa2a9e4SAida Mynzhasova 		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
3984fa2a9e4SAida Mynzhasova 		.write = ad5446_write,
3994fa2a9e4SAida Mynzhasova 	},
400dbdc025bSLars-Peter Clausen 	[ID_AD5620_2500] = {
401dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
402dbdc025bSLars-Peter Clausen 		.int_vref_mv = 2500,
403dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
404dbdc025bSLars-Peter Clausen 	},
405dbdc025bSLars-Peter Clausen 	[ID_AD5620_1250] = {
406dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
407dbdc025bSLars-Peter Clausen 		.int_vref_mv = 1250,
408dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
409dbdc025bSLars-Peter Clausen 	},
410dbdc025bSLars-Peter Clausen 	[ID_AD5640_2500] = {
411dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
412dbdc025bSLars-Peter Clausen 		.int_vref_mv = 2500,
413dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
414dbdc025bSLars-Peter Clausen 	},
415dbdc025bSLars-Peter Clausen 	[ID_AD5640_1250] = {
416dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
417dbdc025bSLars-Peter Clausen 		.int_vref_mv = 1250,
418dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
419dbdc025bSLars-Peter Clausen 	},
420dbdc025bSLars-Peter Clausen 	[ID_AD5660_2500] = {
421dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
422dbdc025bSLars-Peter Clausen 		.int_vref_mv = 2500,
423dbdc025bSLars-Peter Clausen 		.write = ad5660_write,
424dbdc025bSLars-Peter Clausen 	},
425dbdc025bSLars-Peter Clausen 	[ID_AD5660_1250] = {
426dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
427dbdc025bSLars-Peter Clausen 		.int_vref_mv = 1250,
428dbdc025bSLars-Peter Clausen 		.write = ad5660_write,
429dbdc025bSLars-Peter Clausen 	},
430dbdc025bSLars-Peter Clausen 	[ID_AD5662] = {
431dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
432dbdc025bSLars-Peter Clausen 		.write = ad5660_write,
433dbdc025bSLars-Peter Clausen 	},
434dbdc025bSLars-Peter Clausen };
435dbdc025bSLars-Peter Clausen 
4363ec36a2cSJean-Francois Dagenais static const struct spi_device_id ad5446_spi_ids[] = {
4372fafbce2SLars-Peter Clausen 	{"ad5300", ID_AD5300},
4382fafbce2SLars-Peter Clausen 	{"ad5310", ID_AD5310},
4392fafbce2SLars-Peter Clausen 	{"ad5320", ID_AD5320},
440dbdc025bSLars-Peter Clausen 	{"ad5444", ID_AD5444},
441dbdc025bSLars-Peter Clausen 	{"ad5446", ID_AD5446},
442779c0c46SLars-Peter Clausen 	{"ad5450", ID_AD5450},
443779c0c46SLars-Peter Clausen 	{"ad5451", ID_AD5451},
444779c0c46SLars-Peter Clausen 	{"ad5452", ID_AD5444}, /* ad5452 is compatible to the ad5444 */
445779c0c46SLars-Peter Clausen 	{"ad5453", ID_AD5446}, /* ad5453 is compatible to the ad5446 */
446dbdc025bSLars-Peter Clausen 	{"ad5512a", ID_AD5512A},
447dbdc025bSLars-Peter Clausen 	{"ad5541a", ID_AD5541A},
448dbdc025bSLars-Peter Clausen 	{"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
449dbdc025bSLars-Peter Clausen 	{"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */
450dbdc025bSLars-Peter Clausen 	{"ad5553", ID_AD5553},
451dbdc025bSLars-Peter Clausen 	{"ad5601", ID_AD5601},
452dbdc025bSLars-Peter Clausen 	{"ad5611", ID_AD5611},
453dbdc025bSLars-Peter Clausen 	{"ad5621", ID_AD5621},
4544fa2a9e4SAida Mynzhasova 	{"ad5641", ID_AD5641},
455dbdc025bSLars-Peter Clausen 	{"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
456dbdc025bSLars-Peter Clausen 	{"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
457dbdc025bSLars-Peter Clausen 	{"ad5640-2500", ID_AD5640_2500},
458dbdc025bSLars-Peter Clausen 	{"ad5640-1250", ID_AD5640_1250},
459dbdc025bSLars-Peter Clausen 	{"ad5660-2500", ID_AD5660_2500},
460dbdc025bSLars-Peter Clausen 	{"ad5660-1250", ID_AD5660_1250},
461dbdc025bSLars-Peter Clausen 	{"ad5662", ID_AD5662},
4629cad3b98SLukas Wunner 	{"dac081s101", ID_AD5300}, /* compatible Texas Instruments chips */
4639cad3b98SLukas Wunner 	{"dac101s101", ID_AD5310},
4649cad3b98SLukas Wunner 	{"dac121s101", ID_AD5320},
46549b3f874SLukas Wunner 	{"dac7512", ID_AD5320},
466dbdc025bSLars-Peter Clausen 	{}
467dbdc025bSLars-Peter Clausen };
4683ec36a2cSJean-Francois Dagenais MODULE_DEVICE_TABLE(spi, ad5446_spi_ids);
469dbdc025bSLars-Peter Clausen 
47049b3f874SLukas Wunner #ifdef CONFIG_OF
47149b3f874SLukas Wunner static const struct of_device_id ad5446_of_ids[] = {
47249b3f874SLukas Wunner 	{ .compatible = "ti,dac7512" },
47349b3f874SLukas Wunner 	{ }
47449b3f874SLukas Wunner };
47549b3f874SLukas Wunner MODULE_DEVICE_TABLE(of, ad5446_of_ids);
47649b3f874SLukas Wunner #endif
47749b3f874SLukas Wunner 
478fc52692cSGreg Kroah-Hartman static int ad5446_spi_probe(struct spi_device *spi)
4793ec36a2cSJean-Francois Dagenais {
4803ec36a2cSJean-Francois Dagenais 	const struct spi_device_id *id = spi_get_device_id(spi);
4813ec36a2cSJean-Francois Dagenais 
4823ec36a2cSJean-Francois Dagenais 	return ad5446_probe(&spi->dev, id->name,
4833ec36a2cSJean-Francois Dagenais 		&ad5446_spi_chip_info[id->driver_data]);
4843ec36a2cSJean-Francois Dagenais }
4853ec36a2cSJean-Francois Dagenais 
486fc52692cSGreg Kroah-Hartman static int ad5446_spi_remove(struct spi_device *spi)
4873ec36a2cSJean-Francois Dagenais {
4883ec36a2cSJean-Francois Dagenais 	return ad5446_remove(&spi->dev);
4893ec36a2cSJean-Francois Dagenais }
4903ec36a2cSJean-Francois Dagenais 
4913ec36a2cSJean-Francois Dagenais static struct spi_driver ad5446_spi_driver = {
492dbdc025bSLars-Peter Clausen 	.driver = {
493dbdc025bSLars-Peter Clausen 		.name	= "ad5446",
49449b3f874SLukas Wunner 		.of_match_table = of_match_ptr(ad5446_of_ids),
495dbdc025bSLars-Peter Clausen 	},
4963ec36a2cSJean-Francois Dagenais 	.probe		= ad5446_spi_probe,
497fc52692cSGreg Kroah-Hartman 	.remove		= ad5446_spi_remove,
4983ec36a2cSJean-Francois Dagenais 	.id_table	= ad5446_spi_ids,
499dbdc025bSLars-Peter Clausen };
5003ec36a2cSJean-Francois Dagenais 
5013ec36a2cSJean-Francois Dagenais static int __init ad5446_spi_register_driver(void)
5023ec36a2cSJean-Francois Dagenais {
5033ec36a2cSJean-Francois Dagenais 	return spi_register_driver(&ad5446_spi_driver);
5043ec36a2cSJean-Francois Dagenais }
5053ec36a2cSJean-Francois Dagenais 
5063ec36a2cSJean-Francois Dagenais static void ad5446_spi_unregister_driver(void)
5073ec36a2cSJean-Francois Dagenais {
5083ec36a2cSJean-Francois Dagenais 	spi_unregister_driver(&ad5446_spi_driver);
5093ec36a2cSJean-Francois Dagenais }
5103ec36a2cSJean-Francois Dagenais 
5113ec36a2cSJean-Francois Dagenais #else
5123ec36a2cSJean-Francois Dagenais 
5133ec36a2cSJean-Francois Dagenais static inline int ad5446_spi_register_driver(void) { return 0; }
5143ec36a2cSJean-Francois Dagenais static inline void ad5446_spi_unregister_driver(void) { }
5153ec36a2cSJean-Francois Dagenais 
5163ec36a2cSJean-Francois Dagenais #endif
5173ec36a2cSJean-Francois Dagenais 
5183ec36a2cSJean-Francois Dagenais #if IS_ENABLED(CONFIG_I2C)
5193ec36a2cSJean-Francois Dagenais 
5203ec36a2cSJean-Francois Dagenais static int ad5622_write(struct ad5446_state *st, unsigned val)
5213ec36a2cSJean-Francois Dagenais {
5223ec36a2cSJean-Francois Dagenais 	struct i2c_client *client = to_i2c_client(st->dev);
5233ec36a2cSJean-Francois Dagenais 	__be16 data = cpu_to_be16(val);
5243ec36a2cSJean-Francois Dagenais 
5253ec36a2cSJean-Francois Dagenais 	return i2c_master_send(client, (char *)&data, sizeof(data));
5263ec36a2cSJean-Francois Dagenais }
5273ec36a2cSJean-Francois Dagenais 
5283ec36a2cSJean-Francois Dagenais /**
5293ec36a2cSJean-Francois Dagenais  * ad5446_supported_i2c_device_ids:
5303ec36a2cSJean-Francois Dagenais  * The AD5620/40/60 parts are available in different fixed internal reference
5313ec36a2cSJean-Francois Dagenais  * voltage options. The actual part numbers may look differently
5323ec36a2cSJean-Francois Dagenais  * (and a bit cryptic), however this style is used to make clear which
5333ec36a2cSJean-Francois Dagenais  * parts are supported here.
5343ec36a2cSJean-Francois Dagenais  */
5353ec36a2cSJean-Francois Dagenais enum ad5446_supported_i2c_device_ids {
5363ec36a2cSJean-Francois Dagenais 	ID_AD5602,
5373ec36a2cSJean-Francois Dagenais 	ID_AD5612,
5383ec36a2cSJean-Francois Dagenais 	ID_AD5622,
5393ec36a2cSJean-Francois Dagenais };
5403ec36a2cSJean-Francois Dagenais 
5413ec36a2cSJean-Francois Dagenais static const struct ad5446_chip_info ad5446_i2c_chip_info[] = {
5423ec36a2cSJean-Francois Dagenais 	[ID_AD5602] = {
5433ec36a2cSJean-Francois Dagenais 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
5443ec36a2cSJean-Francois Dagenais 		.write = ad5622_write,
5453ec36a2cSJean-Francois Dagenais 	},
5463ec36a2cSJean-Francois Dagenais 	[ID_AD5612] = {
5473ec36a2cSJean-Francois Dagenais 		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
5483ec36a2cSJean-Francois Dagenais 		.write = ad5622_write,
5493ec36a2cSJean-Francois Dagenais 	},
5503ec36a2cSJean-Francois Dagenais 	[ID_AD5622] = {
5513ec36a2cSJean-Francois Dagenais 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
5523ec36a2cSJean-Francois Dagenais 		.write = ad5622_write,
5533ec36a2cSJean-Francois Dagenais 	},
5543ec36a2cSJean-Francois Dagenais };
5553ec36a2cSJean-Francois Dagenais 
556fc52692cSGreg Kroah-Hartman static int ad5446_i2c_probe(struct i2c_client *i2c,
5573ec36a2cSJean-Francois Dagenais 			    const struct i2c_device_id *id)
5583ec36a2cSJean-Francois Dagenais {
5593ec36a2cSJean-Francois Dagenais 	return ad5446_probe(&i2c->dev, id->name,
5603ec36a2cSJean-Francois Dagenais 		&ad5446_i2c_chip_info[id->driver_data]);
5613ec36a2cSJean-Francois Dagenais }
5623ec36a2cSJean-Francois Dagenais 
563fc52692cSGreg Kroah-Hartman static int ad5446_i2c_remove(struct i2c_client *i2c)
5643ec36a2cSJean-Francois Dagenais {
5653ec36a2cSJean-Francois Dagenais 	return ad5446_remove(&i2c->dev);
5663ec36a2cSJean-Francois Dagenais }
5673ec36a2cSJean-Francois Dagenais 
5683ec36a2cSJean-Francois Dagenais static const struct i2c_device_id ad5446_i2c_ids[] = {
569bf832380SLars-Peter Clausen 	{"ad5301", ID_AD5602},
570bf832380SLars-Peter Clausen 	{"ad5311", ID_AD5612},
571bf832380SLars-Peter Clausen 	{"ad5321", ID_AD5622},
5723ec36a2cSJean-Francois Dagenais 	{"ad5602", ID_AD5602},
5733ec36a2cSJean-Francois Dagenais 	{"ad5612", ID_AD5612},
5743ec36a2cSJean-Francois Dagenais 	{"ad5622", ID_AD5622},
5753ec36a2cSJean-Francois Dagenais 	{}
5763ec36a2cSJean-Francois Dagenais };
5773ec36a2cSJean-Francois Dagenais MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids);
5783ec36a2cSJean-Francois Dagenais 
5793ec36a2cSJean-Francois Dagenais static struct i2c_driver ad5446_i2c_driver = {
5803ec36a2cSJean-Francois Dagenais 	.driver = {
5813ec36a2cSJean-Francois Dagenais 		   .name = "ad5446",
5823ec36a2cSJean-Francois Dagenais 	},
5833ec36a2cSJean-Francois Dagenais 	.probe = ad5446_i2c_probe,
584fc52692cSGreg Kroah-Hartman 	.remove = ad5446_i2c_remove,
5853ec36a2cSJean-Francois Dagenais 	.id_table = ad5446_i2c_ids,
5863ec36a2cSJean-Francois Dagenais };
5873ec36a2cSJean-Francois Dagenais 
5883ec36a2cSJean-Francois Dagenais static int __init ad5446_i2c_register_driver(void)
5893ec36a2cSJean-Francois Dagenais {
5903ec36a2cSJean-Francois Dagenais 	return i2c_add_driver(&ad5446_i2c_driver);
5913ec36a2cSJean-Francois Dagenais }
5923ec36a2cSJean-Francois Dagenais 
5933ec36a2cSJean-Francois Dagenais static void __exit ad5446_i2c_unregister_driver(void)
5943ec36a2cSJean-Francois Dagenais {
5953ec36a2cSJean-Francois Dagenais 	i2c_del_driver(&ad5446_i2c_driver);
5963ec36a2cSJean-Francois Dagenais }
5973ec36a2cSJean-Francois Dagenais 
5983ec36a2cSJean-Francois Dagenais #else
5993ec36a2cSJean-Francois Dagenais 
6003ec36a2cSJean-Francois Dagenais static inline int ad5446_i2c_register_driver(void) { return 0; }
6013ec36a2cSJean-Francois Dagenais static inline void ad5446_i2c_unregister_driver(void) { }
6023ec36a2cSJean-Francois Dagenais 
6033ec36a2cSJean-Francois Dagenais #endif
6043ec36a2cSJean-Francois Dagenais 
6053ec36a2cSJean-Francois Dagenais static int __init ad5446_init(void)
6063ec36a2cSJean-Francois Dagenais {
6073ec36a2cSJean-Francois Dagenais 	int ret;
6083ec36a2cSJean-Francois Dagenais 
6093ec36a2cSJean-Francois Dagenais 	ret = ad5446_spi_register_driver();
6103ec36a2cSJean-Francois Dagenais 	if (ret)
6113ec36a2cSJean-Francois Dagenais 		return ret;
6123ec36a2cSJean-Francois Dagenais 
6133ec36a2cSJean-Francois Dagenais 	ret = ad5446_i2c_register_driver();
6143ec36a2cSJean-Francois Dagenais 	if (ret) {
6153ec36a2cSJean-Francois Dagenais 		ad5446_spi_unregister_driver();
6163ec36a2cSJean-Francois Dagenais 		return ret;
6173ec36a2cSJean-Francois Dagenais 	}
6183ec36a2cSJean-Francois Dagenais 
6193ec36a2cSJean-Francois Dagenais 	return 0;
6203ec36a2cSJean-Francois Dagenais }
6213ec36a2cSJean-Francois Dagenais module_init(ad5446_init);
6223ec36a2cSJean-Francois Dagenais 
6233ec36a2cSJean-Francois Dagenais static void __exit ad5446_exit(void)
6243ec36a2cSJean-Francois Dagenais {
6253ec36a2cSJean-Francois Dagenais 	ad5446_i2c_unregister_driver();
6263ec36a2cSJean-Francois Dagenais 	ad5446_spi_unregister_driver();
6273ec36a2cSJean-Francois Dagenais }
6283ec36a2cSJean-Francois Dagenais module_exit(ad5446_exit);
629dbdc025bSLars-Peter Clausen 
6309920ed25SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
631dbdc025bSLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
632dbdc025bSLars-Peter Clausen MODULE_LICENSE("GPL v2");
633