xref: /openbmc/linux/drivers/iio/dac/ad5446.c (revision ffc7c517)
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>
20b49e6eb1SJonathan Cameron #include <linux/mod_devicetable.h>
21dbdc025bSLars-Peter Clausen 
22dbdc025bSLars-Peter Clausen #include <linux/iio/iio.h>
23dbdc025bSLars-Peter Clausen #include <linux/iio/sysfs.h>
24dbdc025bSLars-Peter Clausen 
256ef9d68bSAndy Shevchenko #include <asm/unaligned.h>
266ef9d68bSAndy Shevchenko 
272e15c903SJean-Francois Dagenais #define MODE_PWRDWN_1k		0x1
282e15c903SJean-Francois Dagenais #define MODE_PWRDWN_100k	0x2
292e15c903SJean-Francois Dagenais #define MODE_PWRDWN_TRISTATE	0x3
302e15c903SJean-Francois Dagenais 
312e15c903SJean-Francois Dagenais /**
322e15c903SJean-Francois Dagenais  * struct ad5446_state - driver instance specific data
33af390b8cSLee Jones  * @dev:		this device
342e15c903SJean-Francois Dagenais  * @chip_info:		chip model specific constants, available modes etc
352e15c903SJean-Francois Dagenais  * @reg:		supply regulator
362e15c903SJean-Francois Dagenais  * @vref_mv:		actual reference voltage used
37af390b8cSLee Jones  * @cached_val:		store/retrieve values during power down
38af390b8cSLee Jones  * @pwr_down_mode:	power down mode (1k, 100k or tristate)
39af390b8cSLee Jones  * @pwr_down:		true if the device is in power down
40af390b8cSLee Jones  * @lock:		lock to protect the data buffer during write ops
412e15c903SJean-Francois Dagenais  */
422e15c903SJean-Francois Dagenais 
432e15c903SJean-Francois Dagenais struct ad5446_state {
442e15c903SJean-Francois Dagenais 	struct device		*dev;
452e15c903SJean-Francois Dagenais 	const struct ad5446_chip_info	*chip_info;
462e15c903SJean-Francois Dagenais 	struct regulator		*reg;
472e15c903SJean-Francois Dagenais 	unsigned short			vref_mv;
482e15c903SJean-Francois Dagenais 	unsigned			cached_val;
492e15c903SJean-Francois Dagenais 	unsigned			pwr_down_mode;
502e15c903SJean-Francois Dagenais 	unsigned			pwr_down;
510b4b5925SSergiu Cuciurean 	struct mutex			lock;
522e15c903SJean-Francois Dagenais };
532e15c903SJean-Francois Dagenais 
542e15c903SJean-Francois Dagenais /**
552e15c903SJean-Francois Dagenais  * struct ad5446_chip_info - chip specific information
562e15c903SJean-Francois Dagenais  * @channel:		channel spec for the DAC
572e15c903SJean-Francois Dagenais  * @int_vref_mv:	AD5620/40/60: the internal reference voltage
582e15c903SJean-Francois Dagenais  * @write:		chip specific helper function to write to the register
592e15c903SJean-Francois Dagenais  */
602e15c903SJean-Francois Dagenais 
612e15c903SJean-Francois Dagenais struct ad5446_chip_info {
622e15c903SJean-Francois Dagenais 	struct iio_chan_spec	channel;
632e15c903SJean-Francois Dagenais 	u16			int_vref_mv;
642e15c903SJean-Francois Dagenais 	int			(*write)(struct ad5446_state *st, unsigned val);
652e15c903SJean-Francois Dagenais };
66dbdc025bSLars-Peter Clausen 
67dbdc025bSLars-Peter Clausen static const char * const ad5446_powerdown_modes[] = {
68dbdc025bSLars-Peter Clausen 	"1kohm_to_gnd", "100kohm_to_gnd", "three_state"
69dbdc025bSLars-Peter Clausen };
70dbdc025bSLars-Peter Clausen 
71dbdc025bSLars-Peter Clausen static int ad5446_set_powerdown_mode(struct iio_dev *indio_dev,
72dbdc025bSLars-Peter Clausen 	const struct iio_chan_spec *chan, unsigned int mode)
73dbdc025bSLars-Peter Clausen {
74dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
75dbdc025bSLars-Peter Clausen 
76dbdc025bSLars-Peter Clausen 	st->pwr_down_mode = mode + 1;
77dbdc025bSLars-Peter Clausen 
78dbdc025bSLars-Peter Clausen 	return 0;
79dbdc025bSLars-Peter Clausen }
80dbdc025bSLars-Peter Clausen 
81dbdc025bSLars-Peter Clausen static int ad5446_get_powerdown_mode(struct iio_dev *indio_dev,
82dbdc025bSLars-Peter Clausen 	const struct iio_chan_spec *chan)
83dbdc025bSLars-Peter Clausen {
84dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
85dbdc025bSLars-Peter Clausen 
86dbdc025bSLars-Peter Clausen 	return st->pwr_down_mode - 1;
87dbdc025bSLars-Peter Clausen }
88dbdc025bSLars-Peter Clausen 
89dbdc025bSLars-Peter Clausen static const struct iio_enum ad5446_powerdown_mode_enum = {
90dbdc025bSLars-Peter Clausen 	.items = ad5446_powerdown_modes,
91dbdc025bSLars-Peter Clausen 	.num_items = ARRAY_SIZE(ad5446_powerdown_modes),
92dbdc025bSLars-Peter Clausen 	.get = ad5446_get_powerdown_mode,
93dbdc025bSLars-Peter Clausen 	.set = ad5446_set_powerdown_mode,
94dbdc025bSLars-Peter Clausen };
95dbdc025bSLars-Peter Clausen 
96dbdc025bSLars-Peter Clausen static ssize_t ad5446_read_dac_powerdown(struct iio_dev *indio_dev,
97dbdc025bSLars-Peter Clausen 					   uintptr_t private,
98dbdc025bSLars-Peter Clausen 					   const struct iio_chan_spec *chan,
99dbdc025bSLars-Peter Clausen 					   char *buf)
100dbdc025bSLars-Peter Clausen {
101dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
102dbdc025bSLars-Peter Clausen 
103f46ac009SLars-Peter Clausen 	return sysfs_emit(buf, "%d\n", st->pwr_down);
104dbdc025bSLars-Peter Clausen }
105dbdc025bSLars-Peter Clausen 
106dbdc025bSLars-Peter Clausen static ssize_t ad5446_write_dac_powerdown(struct iio_dev *indio_dev,
107dbdc025bSLars-Peter Clausen 					    uintptr_t private,
108dbdc025bSLars-Peter Clausen 					    const struct iio_chan_spec *chan,
109dbdc025bSLars-Peter Clausen 					    const char *buf, size_t len)
110dbdc025bSLars-Peter Clausen {
111dbdc025bSLars-Peter Clausen 	struct ad5446_state *st = iio_priv(indio_dev);
112dbdc025bSLars-Peter Clausen 	unsigned int shift;
113dbdc025bSLars-Peter Clausen 	unsigned int val;
114dbdc025bSLars-Peter Clausen 	bool powerdown;
115dbdc025bSLars-Peter Clausen 	int ret;
116dbdc025bSLars-Peter Clausen 
117dbdc025bSLars-Peter Clausen 	ret = strtobool(buf, &powerdown);
118dbdc025bSLars-Peter Clausen 	if (ret)
119dbdc025bSLars-Peter Clausen 		return ret;
120dbdc025bSLars-Peter Clausen 
1210b4b5925SSergiu Cuciurean 	mutex_lock(&st->lock);
122dbdc025bSLars-Peter Clausen 	st->pwr_down = powerdown;
123dbdc025bSLars-Peter Clausen 
124dbdc025bSLars-Peter Clausen 	if (st->pwr_down) {
125dbdc025bSLars-Peter Clausen 		shift = chan->scan_type.realbits + chan->scan_type.shift;
126dbdc025bSLars-Peter Clausen 		val = st->pwr_down_mode << shift;
127dbdc025bSLars-Peter Clausen 	} else {
128dbdc025bSLars-Peter Clausen 		val = st->cached_val;
129dbdc025bSLars-Peter Clausen 	}
130dbdc025bSLars-Peter Clausen 
131dbdc025bSLars-Peter Clausen 	ret = st->chip_info->write(st, val);
1320b4b5925SSergiu Cuciurean 	mutex_unlock(&st->lock);
133dbdc025bSLars-Peter Clausen 
134dbdc025bSLars-Peter Clausen 	return ret ? ret : len;
135dbdc025bSLars-Peter Clausen }
136dbdc025bSLars-Peter Clausen 
1373ec36a2cSJean-Francois Dagenais static const struct iio_chan_spec_ext_info ad5446_ext_info_powerdown[] = {
138dbdc025bSLars-Peter Clausen 	{
139dbdc025bSLars-Peter Clausen 		.name = "powerdown",
140dbdc025bSLars-Peter Clausen 		.read = ad5446_read_dac_powerdown,
141dbdc025bSLars-Peter Clausen 		.write = ad5446_write_dac_powerdown,
1423704432fSJonathan Cameron 		.shared = IIO_SEPARATE,
143dbdc025bSLars-Peter Clausen 	},
1443704432fSJonathan Cameron 	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5446_powerdown_mode_enum),
145*ffc7c517SAntoniu Miclaus 	IIO_ENUM_AVAILABLE("powerdown_mode", IIO_SHARED_BY_TYPE, &ad5446_powerdown_mode_enum),
146dbdc025bSLars-Peter Clausen 	{ },
147dbdc025bSLars-Peter Clausen };
148dbdc025bSLars-Peter Clausen 
149e3019c21SJonathan Cameron #define _AD5446_CHANNEL(bits, storage, _shift, ext) { \
150dbdc025bSLars-Peter Clausen 	.type = IIO_VOLTAGE, \
151dbdc025bSLars-Peter Clausen 	.indexed = 1, \
152dbdc025bSLars-Peter Clausen 	.output = 1, \
153dbdc025bSLars-Peter Clausen 	.channel = 0, \
1542f6a4a44SJonathan Cameron 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
1552f6a4a44SJonathan Cameron 	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
156e3019c21SJonathan Cameron 	.scan_type = { \
157e3019c21SJonathan Cameron 		.sign = 'u', \
158e3019c21SJonathan Cameron 		.realbits = (bits), \
159e3019c21SJonathan Cameron 		.storagebits = (storage), \
160e3019c21SJonathan Cameron 		.shift = (_shift), \
161e3019c21SJonathan Cameron 		}, \
162dbdc025bSLars-Peter Clausen 	.ext_info = (ext), \
163dbdc025bSLars-Peter Clausen }
164dbdc025bSLars-Peter Clausen 
165dbdc025bSLars-Peter Clausen #define AD5446_CHANNEL(bits, storage, shift) \
166dbdc025bSLars-Peter Clausen 	_AD5446_CHANNEL(bits, storage, shift, NULL)
167dbdc025bSLars-Peter Clausen 
168dbdc025bSLars-Peter Clausen #define AD5446_CHANNEL_POWERDOWN(bits, storage, shift) \
1693ec36a2cSJean-Francois Dagenais 	_AD5446_CHANNEL(bits, storage, shift, ad5446_ext_info_powerdown)
170dbdc025bSLars-Peter Clausen 
1713ec36a2cSJean-Francois Dagenais static int ad5446_read_raw(struct iio_dev *indio_dev,
1723ec36a2cSJean-Francois Dagenais 			   struct iio_chan_spec const *chan,
1733ec36a2cSJean-Francois Dagenais 			   int *val,
1743ec36a2cSJean-Francois Dagenais 			   int *val2,
1753ec36a2cSJean-Francois Dagenais 			   long m)
1763ec36a2cSJean-Francois Dagenais {
1773ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st = iio_priv(indio_dev);
1783ec36a2cSJean-Francois Dagenais 
1793ec36a2cSJean-Francois Dagenais 	switch (m) {
1803ec36a2cSJean-Francois Dagenais 	case IIO_CHAN_INFO_RAW:
1813ec36a2cSJean-Francois Dagenais 		*val = st->cached_val;
1823ec36a2cSJean-Francois Dagenais 		return IIO_VAL_INT;
1833ec36a2cSJean-Francois Dagenais 	case IIO_CHAN_INFO_SCALE:
1840a99b601SLars-Peter Clausen 		*val = st->vref_mv;
1850a99b601SLars-Peter Clausen 		*val2 = chan->scan_type.realbits;
1860a99b601SLars-Peter Clausen 		return IIO_VAL_FRACTIONAL_LOG2;
1873ec36a2cSJean-Francois Dagenais 	}
1883ec36a2cSJean-Francois Dagenais 	return -EINVAL;
1893ec36a2cSJean-Francois Dagenais }
1903ec36a2cSJean-Francois Dagenais 
1913ec36a2cSJean-Francois Dagenais static int ad5446_write_raw(struct iio_dev *indio_dev,
1923ec36a2cSJean-Francois Dagenais 			       struct iio_chan_spec const *chan,
1933ec36a2cSJean-Francois Dagenais 			       int val,
1943ec36a2cSJean-Francois Dagenais 			       int val2,
1953ec36a2cSJean-Francois Dagenais 			       long mask)
1963ec36a2cSJean-Francois Dagenais {
1973ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st = iio_priv(indio_dev);
1983ec36a2cSJean-Francois Dagenais 	int ret = 0;
1993ec36a2cSJean-Francois Dagenais 
2003ec36a2cSJean-Francois Dagenais 	switch (mask) {
2013ec36a2cSJean-Francois Dagenais 	case IIO_CHAN_INFO_RAW:
2023ec36a2cSJean-Francois Dagenais 		if (val >= (1 << chan->scan_type.realbits) || val < 0)
2033ec36a2cSJean-Francois Dagenais 			return -EINVAL;
2043ec36a2cSJean-Francois Dagenais 
2053ec36a2cSJean-Francois Dagenais 		val <<= chan->scan_type.shift;
2060b4b5925SSergiu Cuciurean 		mutex_lock(&st->lock);
2073ec36a2cSJean-Francois Dagenais 		st->cached_val = val;
2083ec36a2cSJean-Francois Dagenais 		if (!st->pwr_down)
2093ec36a2cSJean-Francois Dagenais 			ret = st->chip_info->write(st, val);
2100b4b5925SSergiu Cuciurean 		mutex_unlock(&st->lock);
2113ec36a2cSJean-Francois Dagenais 		break;
2123ec36a2cSJean-Francois Dagenais 	default:
2133ec36a2cSJean-Francois Dagenais 		ret = -EINVAL;
2143ec36a2cSJean-Francois Dagenais 	}
2153ec36a2cSJean-Francois Dagenais 
2163ec36a2cSJean-Francois Dagenais 	return ret;
2173ec36a2cSJean-Francois Dagenais }
2183ec36a2cSJean-Francois Dagenais 
2193ec36a2cSJean-Francois Dagenais static const struct iio_info ad5446_info = {
2203ec36a2cSJean-Francois Dagenais 	.read_raw = ad5446_read_raw,
2213ec36a2cSJean-Francois Dagenais 	.write_raw = ad5446_write_raw,
2223ec36a2cSJean-Francois Dagenais };
2233ec36a2cSJean-Francois Dagenais 
224fc52692cSGreg Kroah-Hartman static int ad5446_probe(struct device *dev, const char *name,
2253ec36a2cSJean-Francois Dagenais 			const struct ad5446_chip_info *chip_info)
2263ec36a2cSJean-Francois Dagenais {
2273ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st;
2283ec36a2cSJean-Francois Dagenais 	struct iio_dev *indio_dev;
2293ec36a2cSJean-Francois Dagenais 	struct regulator *reg;
2303ec36a2cSJean-Francois Dagenais 	int ret, voltage_uv = 0;
2313ec36a2cSJean-Francois Dagenais 
232ba727295SSachin Kamat 	reg = devm_regulator_get(dev, "vcc");
2333ec36a2cSJean-Francois Dagenais 	if (!IS_ERR(reg)) {
2343ec36a2cSJean-Francois Dagenais 		ret = regulator_enable(reg);
2353ec36a2cSJean-Francois Dagenais 		if (ret)
236ba727295SSachin Kamat 			return ret;
2373ec36a2cSJean-Francois Dagenais 
23813e57ee2SAxel Lin 		ret = regulator_get_voltage(reg);
23913e57ee2SAxel Lin 		if (ret < 0)
24013e57ee2SAxel Lin 			goto error_disable_reg;
24113e57ee2SAxel Lin 
24213e57ee2SAxel Lin 		voltage_uv = ret;
2433ec36a2cSJean-Francois Dagenais 	}
2443ec36a2cSJean-Francois Dagenais 
245ba727295SSachin Kamat 	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
2463ec36a2cSJean-Francois Dagenais 	if (indio_dev == NULL) {
2473ec36a2cSJean-Francois Dagenais 		ret = -ENOMEM;
2483ec36a2cSJean-Francois Dagenais 		goto error_disable_reg;
2493ec36a2cSJean-Francois Dagenais 	}
2503ec36a2cSJean-Francois Dagenais 	st = iio_priv(indio_dev);
2513ec36a2cSJean-Francois Dagenais 	st->chip_info = chip_info;
2523ec36a2cSJean-Francois Dagenais 
2533ec36a2cSJean-Francois Dagenais 	dev_set_drvdata(dev, indio_dev);
2543ec36a2cSJean-Francois Dagenais 	st->reg = reg;
2553ec36a2cSJean-Francois Dagenais 	st->dev = dev;
2563ec36a2cSJean-Francois Dagenais 
2573ec36a2cSJean-Francois Dagenais 	indio_dev->name = name;
2583ec36a2cSJean-Francois Dagenais 	indio_dev->info = &ad5446_info;
2593ec36a2cSJean-Francois Dagenais 	indio_dev->modes = INDIO_DIRECT_MODE;
2603ec36a2cSJean-Francois Dagenais 	indio_dev->channels = &st->chip_info->channel;
2613ec36a2cSJean-Francois Dagenais 	indio_dev->num_channels = 1;
2623ec36a2cSJean-Francois Dagenais 
2630b4b5925SSergiu Cuciurean 	mutex_init(&st->lock);
2640b4b5925SSergiu Cuciurean 
2653ec36a2cSJean-Francois Dagenais 	st->pwr_down_mode = MODE_PWRDWN_1k;
2663ec36a2cSJean-Francois Dagenais 
2673ec36a2cSJean-Francois Dagenais 	if (st->chip_info->int_vref_mv)
2683ec36a2cSJean-Francois Dagenais 		st->vref_mv = st->chip_info->int_vref_mv;
2693ec36a2cSJean-Francois Dagenais 	else if (voltage_uv)
2703ec36a2cSJean-Francois Dagenais 		st->vref_mv = voltage_uv / 1000;
2713ec36a2cSJean-Francois Dagenais 	else
2723ec36a2cSJean-Francois Dagenais 		dev_warn(dev, "reference voltage unspecified\n");
2733ec36a2cSJean-Francois Dagenais 
2743ec36a2cSJean-Francois Dagenais 	ret = iio_device_register(indio_dev);
2753ec36a2cSJean-Francois Dagenais 	if (ret)
276ba727295SSachin Kamat 		goto error_disable_reg;
2773ec36a2cSJean-Francois Dagenais 
2783ec36a2cSJean-Francois Dagenais 	return 0;
2793ec36a2cSJean-Francois Dagenais 
2803ec36a2cSJean-Francois Dagenais error_disable_reg:
2813ec36a2cSJean-Francois Dagenais 	if (!IS_ERR(reg))
2823ec36a2cSJean-Francois Dagenais 		regulator_disable(reg);
2833ec36a2cSJean-Francois Dagenais 	return ret;
2843ec36a2cSJean-Francois Dagenais }
2853ec36a2cSJean-Francois Dagenais 
2861f10848fSUwe Kleine-König static void ad5446_remove(struct device *dev)
2873ec36a2cSJean-Francois Dagenais {
2883ec36a2cSJean-Francois Dagenais 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
2893ec36a2cSJean-Francois Dagenais 	struct ad5446_state *st = iio_priv(indio_dev);
2903ec36a2cSJean-Francois Dagenais 
2913ec36a2cSJean-Francois Dagenais 	iio_device_unregister(indio_dev);
292ba727295SSachin Kamat 	if (!IS_ERR(st->reg))
2933ec36a2cSJean-Francois Dagenais 		regulator_disable(st->reg);
2943ec36a2cSJean-Francois Dagenais }
2953ec36a2cSJean-Francois Dagenais 
2963ec36a2cSJean-Francois Dagenais #if IS_ENABLED(CONFIG_SPI_MASTER)
2973ec36a2cSJean-Francois Dagenais 
2983ec36a2cSJean-Francois Dagenais static int ad5446_write(struct ad5446_state *st, unsigned val)
2993ec36a2cSJean-Francois Dagenais {
3003ec36a2cSJean-Francois Dagenais 	struct spi_device *spi = to_spi_device(st->dev);
3013ec36a2cSJean-Francois Dagenais 	__be16 data = cpu_to_be16(val);
3023ec36a2cSJean-Francois Dagenais 
3033ec36a2cSJean-Francois Dagenais 	return spi_write(spi, &data, sizeof(data));
3043ec36a2cSJean-Francois Dagenais }
3053ec36a2cSJean-Francois Dagenais 
3063ec36a2cSJean-Francois Dagenais static int ad5660_write(struct ad5446_state *st, unsigned val)
3073ec36a2cSJean-Francois Dagenais {
3083ec36a2cSJean-Francois Dagenais 	struct spi_device *spi = to_spi_device(st->dev);
3093ec36a2cSJean-Francois Dagenais 	uint8_t data[3];
3103ec36a2cSJean-Francois Dagenais 
3116ef9d68bSAndy Shevchenko 	put_unaligned_be24(val, &data[0]);
3123ec36a2cSJean-Francois Dagenais 
3133ec36a2cSJean-Francois Dagenais 	return spi_write(spi, data, sizeof(data));
3143ec36a2cSJean-Francois Dagenais }
3153ec36a2cSJean-Francois Dagenais 
316af390b8cSLee Jones /*
3173ec36a2cSJean-Francois Dagenais  * ad5446_supported_spi_device_ids:
3183ec36a2cSJean-Francois Dagenais  * The AD5620/40/60 parts are available in different fixed internal reference
3193ec36a2cSJean-Francois Dagenais  * voltage options. The actual part numbers may look differently
3203ec36a2cSJean-Francois Dagenais  * (and a bit cryptic), however this style is used to make clear which
3213ec36a2cSJean-Francois Dagenais  * parts are supported here.
3223ec36a2cSJean-Francois Dagenais  */
3233ec36a2cSJean-Francois Dagenais enum ad5446_supported_spi_device_ids {
3242fafbce2SLars-Peter Clausen 	ID_AD5300,
3252fafbce2SLars-Peter Clausen 	ID_AD5310,
3262fafbce2SLars-Peter Clausen 	ID_AD5320,
3273ec36a2cSJean-Francois Dagenais 	ID_AD5444,
3283ec36a2cSJean-Francois Dagenais 	ID_AD5446,
3293ec36a2cSJean-Francois Dagenais 	ID_AD5450,
3303ec36a2cSJean-Francois Dagenais 	ID_AD5451,
3313ec36a2cSJean-Francois Dagenais 	ID_AD5541A,
3323ec36a2cSJean-Francois Dagenais 	ID_AD5512A,
3333ec36a2cSJean-Francois Dagenais 	ID_AD5553,
3346376cbe5SStefan Popa 	ID_AD5600,
3353ec36a2cSJean-Francois Dagenais 	ID_AD5601,
3363ec36a2cSJean-Francois Dagenais 	ID_AD5611,
3373ec36a2cSJean-Francois Dagenais 	ID_AD5621,
3384fa2a9e4SAida Mynzhasova 	ID_AD5641,
3393ec36a2cSJean-Francois Dagenais 	ID_AD5620_2500,
3403ec36a2cSJean-Francois Dagenais 	ID_AD5620_1250,
3413ec36a2cSJean-Francois Dagenais 	ID_AD5640_2500,
3423ec36a2cSJean-Francois Dagenais 	ID_AD5640_1250,
3433ec36a2cSJean-Francois Dagenais 	ID_AD5660_2500,
3443ec36a2cSJean-Francois Dagenais 	ID_AD5660_1250,
3453ec36a2cSJean-Francois Dagenais 	ID_AD5662,
3463ec36a2cSJean-Francois Dagenais };
3473ec36a2cSJean-Francois Dagenais 
3483ec36a2cSJean-Francois Dagenais static const struct ad5446_chip_info ad5446_spi_chip_info[] = {
3492fafbce2SLars-Peter Clausen 	[ID_AD5300] = {
3502fafbce2SLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
3512fafbce2SLars-Peter Clausen 		.write = ad5446_write,
3522fafbce2SLars-Peter Clausen 	},
3532fafbce2SLars-Peter Clausen 	[ID_AD5310] = {
3542fafbce2SLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
3552fafbce2SLars-Peter Clausen 		.write = ad5446_write,
3562fafbce2SLars-Peter Clausen 	},
3572fafbce2SLars-Peter Clausen 	[ID_AD5320] = {
3582fafbce2SLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
3592fafbce2SLars-Peter Clausen 		.write = ad5446_write,
3602fafbce2SLars-Peter Clausen 	},
361dbdc025bSLars-Peter Clausen 	[ID_AD5444] = {
362dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(12, 16, 2),
363dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
364dbdc025bSLars-Peter Clausen 	},
365dbdc025bSLars-Peter Clausen 	[ID_AD5446] = {
366dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(14, 16, 0),
367dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
368dbdc025bSLars-Peter Clausen 	},
369779c0c46SLars-Peter Clausen 	[ID_AD5450] = {
370779c0c46SLars-Peter Clausen 		.channel = AD5446_CHANNEL(8, 16, 6),
371779c0c46SLars-Peter Clausen 		.write = ad5446_write,
372779c0c46SLars-Peter Clausen 	},
373779c0c46SLars-Peter Clausen 	[ID_AD5451] = {
374779c0c46SLars-Peter Clausen 		.channel = AD5446_CHANNEL(10, 16, 4),
375779c0c46SLars-Peter Clausen 		.write = ad5446_write,
376779c0c46SLars-Peter Clausen 	},
377dbdc025bSLars-Peter Clausen 	[ID_AD5541A] = {
378dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(16, 16, 0),
379dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
380dbdc025bSLars-Peter Clausen 	},
381dbdc025bSLars-Peter Clausen 	[ID_AD5512A] = {
382dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(12, 16, 4),
383dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
384dbdc025bSLars-Peter Clausen 	},
385dbdc025bSLars-Peter Clausen 	[ID_AD5553] = {
386dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL(14, 16, 0),
387dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
388dbdc025bSLars-Peter Clausen 	},
3896376cbe5SStefan Popa 	[ID_AD5600] = {
3906376cbe5SStefan Popa 		.channel = AD5446_CHANNEL(16, 16, 0),
3916376cbe5SStefan Popa 		.write = ad5446_write,
3926376cbe5SStefan Popa 	},
393dbdc025bSLars-Peter Clausen 	[ID_AD5601] = {
394dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 6),
395dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
396dbdc025bSLars-Peter Clausen 	},
397dbdc025bSLars-Peter Clausen 	[ID_AD5611] = {
398dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 4),
399dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
400dbdc025bSLars-Peter Clausen 	},
401dbdc025bSLars-Peter Clausen 	[ID_AD5621] = {
402dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
403dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
404dbdc025bSLars-Peter Clausen 	},
4054fa2a9e4SAida Mynzhasova 	[ID_AD5641] = {
4064fa2a9e4SAida Mynzhasova 		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
4074fa2a9e4SAida Mynzhasova 		.write = ad5446_write,
4084fa2a9e4SAida Mynzhasova 	},
409dbdc025bSLars-Peter Clausen 	[ID_AD5620_2500] = {
410dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
411dbdc025bSLars-Peter Clausen 		.int_vref_mv = 2500,
412dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
413dbdc025bSLars-Peter Clausen 	},
414dbdc025bSLars-Peter Clausen 	[ID_AD5620_1250] = {
415dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 2),
416dbdc025bSLars-Peter Clausen 		.int_vref_mv = 1250,
417dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
418dbdc025bSLars-Peter Clausen 	},
419dbdc025bSLars-Peter Clausen 	[ID_AD5640_2500] = {
420dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
421dbdc025bSLars-Peter Clausen 		.int_vref_mv = 2500,
422dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
423dbdc025bSLars-Peter Clausen 	},
424dbdc025bSLars-Peter Clausen 	[ID_AD5640_1250] = {
425dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(14, 16, 0),
426dbdc025bSLars-Peter Clausen 		.int_vref_mv = 1250,
427dbdc025bSLars-Peter Clausen 		.write = ad5446_write,
428dbdc025bSLars-Peter Clausen 	},
429dbdc025bSLars-Peter Clausen 	[ID_AD5660_2500] = {
430dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
431dbdc025bSLars-Peter Clausen 		.int_vref_mv = 2500,
432dbdc025bSLars-Peter Clausen 		.write = ad5660_write,
433dbdc025bSLars-Peter Clausen 	},
434dbdc025bSLars-Peter Clausen 	[ID_AD5660_1250] = {
435dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
436dbdc025bSLars-Peter Clausen 		.int_vref_mv = 1250,
437dbdc025bSLars-Peter Clausen 		.write = ad5660_write,
438dbdc025bSLars-Peter Clausen 	},
439dbdc025bSLars-Peter Clausen 	[ID_AD5662] = {
440dbdc025bSLars-Peter Clausen 		.channel = AD5446_CHANNEL_POWERDOWN(16, 16, 0),
441dbdc025bSLars-Peter Clausen 		.write = ad5660_write,
442dbdc025bSLars-Peter Clausen 	},
443dbdc025bSLars-Peter Clausen };
444dbdc025bSLars-Peter Clausen 
4453ec36a2cSJean-Francois Dagenais static const struct spi_device_id ad5446_spi_ids[] = {
4462fafbce2SLars-Peter Clausen 	{"ad5300", ID_AD5300},
4472fafbce2SLars-Peter Clausen 	{"ad5310", ID_AD5310},
4482fafbce2SLars-Peter Clausen 	{"ad5320", ID_AD5320},
449dbdc025bSLars-Peter Clausen 	{"ad5444", ID_AD5444},
450dbdc025bSLars-Peter Clausen 	{"ad5446", ID_AD5446},
451779c0c46SLars-Peter Clausen 	{"ad5450", ID_AD5450},
452779c0c46SLars-Peter Clausen 	{"ad5451", ID_AD5451},
453779c0c46SLars-Peter Clausen 	{"ad5452", ID_AD5444}, /* ad5452 is compatible to the ad5444 */
454779c0c46SLars-Peter Clausen 	{"ad5453", ID_AD5446}, /* ad5453 is compatible to the ad5446 */
455dbdc025bSLars-Peter Clausen 	{"ad5512a", ID_AD5512A},
456dbdc025bSLars-Peter Clausen 	{"ad5541a", ID_AD5541A},
457dbdc025bSLars-Peter Clausen 	{"ad5542a", ID_AD5541A}, /* ad5541a and ad5542a are compatible */
458dbdc025bSLars-Peter Clausen 	{"ad5543", ID_AD5541A}, /* ad5541a and ad5543 are compatible */
459dbdc025bSLars-Peter Clausen 	{"ad5553", ID_AD5553},
4606376cbe5SStefan Popa 	{"ad5600", ID_AD5600},
461dbdc025bSLars-Peter Clausen 	{"ad5601", ID_AD5601},
462dbdc025bSLars-Peter Clausen 	{"ad5611", ID_AD5611},
463dbdc025bSLars-Peter Clausen 	{"ad5621", ID_AD5621},
4644fa2a9e4SAida Mynzhasova 	{"ad5641", ID_AD5641},
465dbdc025bSLars-Peter Clausen 	{"ad5620-2500", ID_AD5620_2500}, /* AD5620/40/60: */
466dbdc025bSLars-Peter Clausen 	{"ad5620-1250", ID_AD5620_1250}, /* part numbers may look differently */
467dbdc025bSLars-Peter Clausen 	{"ad5640-2500", ID_AD5640_2500},
468dbdc025bSLars-Peter Clausen 	{"ad5640-1250", ID_AD5640_1250},
469dbdc025bSLars-Peter Clausen 	{"ad5660-2500", ID_AD5660_2500},
470dbdc025bSLars-Peter Clausen 	{"ad5660-1250", ID_AD5660_1250},
471dbdc025bSLars-Peter Clausen 	{"ad5662", ID_AD5662},
4729cad3b98SLukas Wunner 	{"dac081s101", ID_AD5300}, /* compatible Texas Instruments chips */
4739cad3b98SLukas Wunner 	{"dac101s101", ID_AD5310},
4749cad3b98SLukas Wunner 	{"dac121s101", ID_AD5320},
47549b3f874SLukas Wunner 	{"dac7512", ID_AD5320},
476dbdc025bSLars-Peter Clausen 	{}
477dbdc025bSLars-Peter Clausen };
4783ec36a2cSJean-Francois Dagenais MODULE_DEVICE_TABLE(spi, ad5446_spi_ids);
479dbdc025bSLars-Peter Clausen 
48049b3f874SLukas Wunner static const struct of_device_id ad5446_of_ids[] = {
48149b3f874SLukas Wunner 	{ .compatible = "ti,dac7512" },
48249b3f874SLukas Wunner 	{ }
48349b3f874SLukas Wunner };
48449b3f874SLukas Wunner MODULE_DEVICE_TABLE(of, ad5446_of_ids);
48549b3f874SLukas Wunner 
486fc52692cSGreg Kroah-Hartman static int ad5446_spi_probe(struct spi_device *spi)
4873ec36a2cSJean-Francois Dagenais {
4883ec36a2cSJean-Francois Dagenais 	const struct spi_device_id *id = spi_get_device_id(spi);
4893ec36a2cSJean-Francois Dagenais 
4903ec36a2cSJean-Francois Dagenais 	return ad5446_probe(&spi->dev, id->name,
4913ec36a2cSJean-Francois Dagenais 		&ad5446_spi_chip_info[id->driver_data]);
4923ec36a2cSJean-Francois Dagenais }
4933ec36a2cSJean-Francois Dagenais 
494fc52692cSGreg Kroah-Hartman static int ad5446_spi_remove(struct spi_device *spi)
4953ec36a2cSJean-Francois Dagenais {
4961f10848fSUwe Kleine-König 	ad5446_remove(&spi->dev);
4971f10848fSUwe Kleine-König 
4981f10848fSUwe Kleine-König 	return 0;
4993ec36a2cSJean-Francois Dagenais }
5003ec36a2cSJean-Francois Dagenais 
5013ec36a2cSJean-Francois Dagenais static struct spi_driver ad5446_spi_driver = {
502dbdc025bSLars-Peter Clausen 	.driver = {
503dbdc025bSLars-Peter Clausen 		.name	= "ad5446",
504b49e6eb1SJonathan Cameron 		.of_match_table = ad5446_of_ids,
505dbdc025bSLars-Peter Clausen 	},
5063ec36a2cSJean-Francois Dagenais 	.probe		= ad5446_spi_probe,
507fc52692cSGreg Kroah-Hartman 	.remove		= ad5446_spi_remove,
5083ec36a2cSJean-Francois Dagenais 	.id_table	= ad5446_spi_ids,
509dbdc025bSLars-Peter Clausen };
5103ec36a2cSJean-Francois Dagenais 
5113ec36a2cSJean-Francois Dagenais static int __init ad5446_spi_register_driver(void)
5123ec36a2cSJean-Francois Dagenais {
5133ec36a2cSJean-Francois Dagenais 	return spi_register_driver(&ad5446_spi_driver);
5143ec36a2cSJean-Francois Dagenais }
5153ec36a2cSJean-Francois Dagenais 
5163ec36a2cSJean-Francois Dagenais static void ad5446_spi_unregister_driver(void)
5173ec36a2cSJean-Francois Dagenais {
5183ec36a2cSJean-Francois Dagenais 	spi_unregister_driver(&ad5446_spi_driver);
5193ec36a2cSJean-Francois Dagenais }
5203ec36a2cSJean-Francois Dagenais 
5213ec36a2cSJean-Francois Dagenais #else
5223ec36a2cSJean-Francois Dagenais 
5233ec36a2cSJean-Francois Dagenais static inline int ad5446_spi_register_driver(void) { return 0; }
5243ec36a2cSJean-Francois Dagenais static inline void ad5446_spi_unregister_driver(void) { }
5253ec36a2cSJean-Francois Dagenais 
5263ec36a2cSJean-Francois Dagenais #endif
5273ec36a2cSJean-Francois Dagenais 
5283ec36a2cSJean-Francois Dagenais #if IS_ENABLED(CONFIG_I2C)
5293ec36a2cSJean-Francois Dagenais 
5303ec36a2cSJean-Francois Dagenais static int ad5622_write(struct ad5446_state *st, unsigned val)
5313ec36a2cSJean-Francois Dagenais {
5323ec36a2cSJean-Francois Dagenais 	struct i2c_client *client = to_i2c_client(st->dev);
5333ec36a2cSJean-Francois Dagenais 	__be16 data = cpu_to_be16(val);
534558df982SPekka Korpinen 	int ret;
5353ec36a2cSJean-Francois Dagenais 
536558df982SPekka Korpinen 	ret = i2c_master_send(client, (char *)&data, sizeof(data));
537558df982SPekka Korpinen 	if (ret < 0)
538558df982SPekka Korpinen 		return ret;
539558df982SPekka Korpinen 	if (ret != sizeof(data))
540558df982SPekka Korpinen 		return -EIO;
541558df982SPekka Korpinen 
542558df982SPekka Korpinen 	return 0;
5433ec36a2cSJean-Francois Dagenais }
5443ec36a2cSJean-Francois Dagenais 
545af390b8cSLee Jones /*
5463ec36a2cSJean-Francois Dagenais  * ad5446_supported_i2c_device_ids:
5473ec36a2cSJean-Francois Dagenais  * The AD5620/40/60 parts are available in different fixed internal reference
5483ec36a2cSJean-Francois Dagenais  * voltage options. The actual part numbers may look differently
5493ec36a2cSJean-Francois Dagenais  * (and a bit cryptic), however this style is used to make clear which
5503ec36a2cSJean-Francois Dagenais  * parts are supported here.
5513ec36a2cSJean-Francois Dagenais  */
5523ec36a2cSJean-Francois Dagenais enum ad5446_supported_i2c_device_ids {
5533ec36a2cSJean-Francois Dagenais 	ID_AD5602,
5543ec36a2cSJean-Francois Dagenais 	ID_AD5612,
5553ec36a2cSJean-Francois Dagenais 	ID_AD5622,
5563ec36a2cSJean-Francois Dagenais };
5573ec36a2cSJean-Francois Dagenais 
5583ec36a2cSJean-Francois Dagenais static const struct ad5446_chip_info ad5446_i2c_chip_info[] = {
5593ec36a2cSJean-Francois Dagenais 	[ID_AD5602] = {
5603ec36a2cSJean-Francois Dagenais 		.channel = AD5446_CHANNEL_POWERDOWN(8, 16, 4),
5613ec36a2cSJean-Francois Dagenais 		.write = ad5622_write,
5623ec36a2cSJean-Francois Dagenais 	},
5633ec36a2cSJean-Francois Dagenais 	[ID_AD5612] = {
5643ec36a2cSJean-Francois Dagenais 		.channel = AD5446_CHANNEL_POWERDOWN(10, 16, 2),
5653ec36a2cSJean-Francois Dagenais 		.write = ad5622_write,
5663ec36a2cSJean-Francois Dagenais 	},
5673ec36a2cSJean-Francois Dagenais 	[ID_AD5622] = {
5683ec36a2cSJean-Francois Dagenais 		.channel = AD5446_CHANNEL_POWERDOWN(12, 16, 0),
5693ec36a2cSJean-Francois Dagenais 		.write = ad5622_write,
5703ec36a2cSJean-Francois Dagenais 	},
5713ec36a2cSJean-Francois Dagenais };
5723ec36a2cSJean-Francois Dagenais 
573fc52692cSGreg Kroah-Hartman static int ad5446_i2c_probe(struct i2c_client *i2c,
5743ec36a2cSJean-Francois Dagenais 			    const struct i2c_device_id *id)
5753ec36a2cSJean-Francois Dagenais {
5763ec36a2cSJean-Francois Dagenais 	return ad5446_probe(&i2c->dev, id->name,
5773ec36a2cSJean-Francois Dagenais 		&ad5446_i2c_chip_info[id->driver_data]);
5783ec36a2cSJean-Francois Dagenais }
5793ec36a2cSJean-Francois Dagenais 
580fc52692cSGreg Kroah-Hartman static int ad5446_i2c_remove(struct i2c_client *i2c)
5813ec36a2cSJean-Francois Dagenais {
5821f10848fSUwe Kleine-König 	ad5446_remove(&i2c->dev);
5831f10848fSUwe Kleine-König 
5841f10848fSUwe Kleine-König 	return 0;
5853ec36a2cSJean-Francois Dagenais }
5863ec36a2cSJean-Francois Dagenais 
5873ec36a2cSJean-Francois Dagenais static const struct i2c_device_id ad5446_i2c_ids[] = {
588bf832380SLars-Peter Clausen 	{"ad5301", ID_AD5602},
589bf832380SLars-Peter Clausen 	{"ad5311", ID_AD5612},
590bf832380SLars-Peter Clausen 	{"ad5321", ID_AD5622},
5913ec36a2cSJean-Francois Dagenais 	{"ad5602", ID_AD5602},
5923ec36a2cSJean-Francois Dagenais 	{"ad5612", ID_AD5612},
5933ec36a2cSJean-Francois Dagenais 	{"ad5622", ID_AD5622},
5943ec36a2cSJean-Francois Dagenais 	{}
5953ec36a2cSJean-Francois Dagenais };
5963ec36a2cSJean-Francois Dagenais MODULE_DEVICE_TABLE(i2c, ad5446_i2c_ids);
5973ec36a2cSJean-Francois Dagenais 
5983ec36a2cSJean-Francois Dagenais static struct i2c_driver ad5446_i2c_driver = {
5993ec36a2cSJean-Francois Dagenais 	.driver = {
6003ec36a2cSJean-Francois Dagenais 		   .name = "ad5446",
6013ec36a2cSJean-Francois Dagenais 	},
6023ec36a2cSJean-Francois Dagenais 	.probe = ad5446_i2c_probe,
603fc52692cSGreg Kroah-Hartman 	.remove = ad5446_i2c_remove,
6043ec36a2cSJean-Francois Dagenais 	.id_table = ad5446_i2c_ids,
6053ec36a2cSJean-Francois Dagenais };
6063ec36a2cSJean-Francois Dagenais 
6073ec36a2cSJean-Francois Dagenais static int __init ad5446_i2c_register_driver(void)
6083ec36a2cSJean-Francois Dagenais {
6093ec36a2cSJean-Francois Dagenais 	return i2c_add_driver(&ad5446_i2c_driver);
6103ec36a2cSJean-Francois Dagenais }
6113ec36a2cSJean-Francois Dagenais 
6123ec36a2cSJean-Francois Dagenais static void __exit ad5446_i2c_unregister_driver(void)
6133ec36a2cSJean-Francois Dagenais {
6143ec36a2cSJean-Francois Dagenais 	i2c_del_driver(&ad5446_i2c_driver);
6153ec36a2cSJean-Francois Dagenais }
6163ec36a2cSJean-Francois Dagenais 
6173ec36a2cSJean-Francois Dagenais #else
6183ec36a2cSJean-Francois Dagenais 
6193ec36a2cSJean-Francois Dagenais static inline int ad5446_i2c_register_driver(void) { return 0; }
6203ec36a2cSJean-Francois Dagenais static inline void ad5446_i2c_unregister_driver(void) { }
6213ec36a2cSJean-Francois Dagenais 
6223ec36a2cSJean-Francois Dagenais #endif
6233ec36a2cSJean-Francois Dagenais 
6243ec36a2cSJean-Francois Dagenais static int __init ad5446_init(void)
6253ec36a2cSJean-Francois Dagenais {
6263ec36a2cSJean-Francois Dagenais 	int ret;
6273ec36a2cSJean-Francois Dagenais 
6283ec36a2cSJean-Francois Dagenais 	ret = ad5446_spi_register_driver();
6293ec36a2cSJean-Francois Dagenais 	if (ret)
6303ec36a2cSJean-Francois Dagenais 		return ret;
6313ec36a2cSJean-Francois Dagenais 
6323ec36a2cSJean-Francois Dagenais 	ret = ad5446_i2c_register_driver();
6333ec36a2cSJean-Francois Dagenais 	if (ret) {
6343ec36a2cSJean-Francois Dagenais 		ad5446_spi_unregister_driver();
6353ec36a2cSJean-Francois Dagenais 		return ret;
6363ec36a2cSJean-Francois Dagenais 	}
6373ec36a2cSJean-Francois Dagenais 
6383ec36a2cSJean-Francois Dagenais 	return 0;
6393ec36a2cSJean-Francois Dagenais }
6403ec36a2cSJean-Francois Dagenais module_init(ad5446_init);
6413ec36a2cSJean-Francois Dagenais 
6423ec36a2cSJean-Francois Dagenais static void __exit ad5446_exit(void)
6433ec36a2cSJean-Francois Dagenais {
6443ec36a2cSJean-Francois Dagenais 	ad5446_i2c_unregister_driver();
6453ec36a2cSJean-Francois Dagenais 	ad5446_spi_unregister_driver();
6463ec36a2cSJean-Francois Dagenais }
6473ec36a2cSJean-Francois Dagenais module_exit(ad5446_exit);
648dbdc025bSLars-Peter Clausen 
6499920ed25SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
650dbdc025bSLars-Peter Clausen MODULE_DESCRIPTION("Analog Devices AD5444/AD5446 DAC");
651dbdc025bSLars-Peter Clausen MODULE_LICENSE("GPL v2");
652