xref: /OK3568_Linux_fs/kernel/drivers/iio/dac/ad5686.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * AD5686R, AD5685R, AD5684R Digital to analog converters  driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2011 Analog Devices Inc.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/interrupt.h>
9*4882a593Smuzhiyun #include <linux/fs.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/module.h>
12*4882a593Smuzhiyun #include <linux/kernel.h>
13*4882a593Smuzhiyun #include <linux/slab.h>
14*4882a593Smuzhiyun #include <linux/sysfs.h>
15*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
16*4882a593Smuzhiyun 
17*4882a593Smuzhiyun #include <linux/iio/iio.h>
18*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
19*4882a593Smuzhiyun 
20*4882a593Smuzhiyun #include "ad5686.h"
21*4882a593Smuzhiyun 
22*4882a593Smuzhiyun static const char * const ad5686_powerdown_modes[] = {
23*4882a593Smuzhiyun 	"1kohm_to_gnd",
24*4882a593Smuzhiyun 	"100kohm_to_gnd",
25*4882a593Smuzhiyun 	"three_state"
26*4882a593Smuzhiyun };
27*4882a593Smuzhiyun 
ad5686_get_powerdown_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan)28*4882a593Smuzhiyun static int ad5686_get_powerdown_mode(struct iio_dev *indio_dev,
29*4882a593Smuzhiyun 				     const struct iio_chan_spec *chan)
30*4882a593Smuzhiyun {
31*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
32*4882a593Smuzhiyun 
33*4882a593Smuzhiyun 	return ((st->pwr_down_mode >> (chan->channel * 2)) & 0x3) - 1;
34*4882a593Smuzhiyun }
35*4882a593Smuzhiyun 
ad5686_set_powerdown_mode(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned int mode)36*4882a593Smuzhiyun static int ad5686_set_powerdown_mode(struct iio_dev *indio_dev,
37*4882a593Smuzhiyun 				     const struct iio_chan_spec *chan,
38*4882a593Smuzhiyun 				     unsigned int mode)
39*4882a593Smuzhiyun {
40*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun 	st->pwr_down_mode &= ~(0x3 << (chan->channel * 2));
43*4882a593Smuzhiyun 	st->pwr_down_mode |= ((mode + 1) << (chan->channel * 2));
44*4882a593Smuzhiyun 
45*4882a593Smuzhiyun 	return 0;
46*4882a593Smuzhiyun }
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun static const struct iio_enum ad5686_powerdown_mode_enum = {
49*4882a593Smuzhiyun 	.items = ad5686_powerdown_modes,
50*4882a593Smuzhiyun 	.num_items = ARRAY_SIZE(ad5686_powerdown_modes),
51*4882a593Smuzhiyun 	.get = ad5686_get_powerdown_mode,
52*4882a593Smuzhiyun 	.set = ad5686_set_powerdown_mode,
53*4882a593Smuzhiyun };
54*4882a593Smuzhiyun 
ad5686_read_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)55*4882a593Smuzhiyun static ssize_t ad5686_read_dac_powerdown(struct iio_dev *indio_dev,
56*4882a593Smuzhiyun 		uintptr_t private, const struct iio_chan_spec *chan, char *buf)
57*4882a593Smuzhiyun {
58*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
59*4882a593Smuzhiyun 
60*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", !!(st->pwr_down_mask &
61*4882a593Smuzhiyun 				       (0x3 << (chan->channel * 2))));
62*4882a593Smuzhiyun }
63*4882a593Smuzhiyun 
ad5686_write_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)64*4882a593Smuzhiyun static ssize_t ad5686_write_dac_powerdown(struct iio_dev *indio_dev,
65*4882a593Smuzhiyun 					  uintptr_t private,
66*4882a593Smuzhiyun 					  const struct iio_chan_spec *chan,
67*4882a593Smuzhiyun 					  const char *buf,
68*4882a593Smuzhiyun 					  size_t len)
69*4882a593Smuzhiyun {
70*4882a593Smuzhiyun 	bool readin;
71*4882a593Smuzhiyun 	int ret;
72*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
73*4882a593Smuzhiyun 	unsigned int val, ref_bit_msk;
74*4882a593Smuzhiyun 	u8 shift, address = 0;
75*4882a593Smuzhiyun 
76*4882a593Smuzhiyun 	ret = strtobool(buf, &readin);
77*4882a593Smuzhiyun 	if (ret)
78*4882a593Smuzhiyun 		return ret;
79*4882a593Smuzhiyun 
80*4882a593Smuzhiyun 	if (readin)
81*4882a593Smuzhiyun 		st->pwr_down_mask |= (0x3 << (chan->channel * 2));
82*4882a593Smuzhiyun 	else
83*4882a593Smuzhiyun 		st->pwr_down_mask &= ~(0x3 << (chan->channel * 2));
84*4882a593Smuzhiyun 
85*4882a593Smuzhiyun 	switch (st->chip_info->regmap_type) {
86*4882a593Smuzhiyun 	case AD5310_REGMAP:
87*4882a593Smuzhiyun 		shift = 9;
88*4882a593Smuzhiyun 		ref_bit_msk = AD5310_REF_BIT_MSK;
89*4882a593Smuzhiyun 		break;
90*4882a593Smuzhiyun 	case AD5683_REGMAP:
91*4882a593Smuzhiyun 		shift = 13;
92*4882a593Smuzhiyun 		ref_bit_msk = AD5683_REF_BIT_MSK;
93*4882a593Smuzhiyun 		break;
94*4882a593Smuzhiyun 	case AD5686_REGMAP:
95*4882a593Smuzhiyun 		shift = 0;
96*4882a593Smuzhiyun 		ref_bit_msk = 0;
97*4882a593Smuzhiyun 		/* AD5674R/AD5679R have 16 channels and 2 powerdown registers */
98*4882a593Smuzhiyun 		if (chan->channel > 0x7)
99*4882a593Smuzhiyun 			address = 0x8;
100*4882a593Smuzhiyun 		break;
101*4882a593Smuzhiyun 	case AD5693_REGMAP:
102*4882a593Smuzhiyun 		shift = 13;
103*4882a593Smuzhiyun 		ref_bit_msk = AD5693_REF_BIT_MSK;
104*4882a593Smuzhiyun 		break;
105*4882a593Smuzhiyun 	default:
106*4882a593Smuzhiyun 		return -EINVAL;
107*4882a593Smuzhiyun 	}
108*4882a593Smuzhiyun 
109*4882a593Smuzhiyun 	val = ((st->pwr_down_mask & st->pwr_down_mode) << shift);
110*4882a593Smuzhiyun 	if (!st->use_internal_vref)
111*4882a593Smuzhiyun 		val |= ref_bit_msk;
112*4882a593Smuzhiyun 
113*4882a593Smuzhiyun 	ret = st->write(st, AD5686_CMD_POWERDOWN_DAC,
114*4882a593Smuzhiyun 			address, val >> (address * 2));
115*4882a593Smuzhiyun 
116*4882a593Smuzhiyun 	return ret ? ret : len;
117*4882a593Smuzhiyun }
118*4882a593Smuzhiyun 
ad5686_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long m)119*4882a593Smuzhiyun static int ad5686_read_raw(struct iio_dev *indio_dev,
120*4882a593Smuzhiyun 			   struct iio_chan_spec const *chan,
121*4882a593Smuzhiyun 			   int *val,
122*4882a593Smuzhiyun 			   int *val2,
123*4882a593Smuzhiyun 			   long m)
124*4882a593Smuzhiyun {
125*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
126*4882a593Smuzhiyun 	int ret;
127*4882a593Smuzhiyun 
128*4882a593Smuzhiyun 	switch (m) {
129*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
130*4882a593Smuzhiyun 		mutex_lock(&st->lock);
131*4882a593Smuzhiyun 		ret = st->read(st, chan->address);
132*4882a593Smuzhiyun 		mutex_unlock(&st->lock);
133*4882a593Smuzhiyun 		if (ret < 0)
134*4882a593Smuzhiyun 			return ret;
135*4882a593Smuzhiyun 		*val = (ret >> chan->scan_type.shift) &
136*4882a593Smuzhiyun 			GENMASK(chan->scan_type.realbits - 1, 0);
137*4882a593Smuzhiyun 		return IIO_VAL_INT;
138*4882a593Smuzhiyun 	case IIO_CHAN_INFO_SCALE:
139*4882a593Smuzhiyun 		*val = st->vref_mv;
140*4882a593Smuzhiyun 		*val2 = chan->scan_type.realbits;
141*4882a593Smuzhiyun 		return IIO_VAL_FRACTIONAL_LOG2;
142*4882a593Smuzhiyun 	}
143*4882a593Smuzhiyun 	return -EINVAL;
144*4882a593Smuzhiyun }
145*4882a593Smuzhiyun 
ad5686_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)146*4882a593Smuzhiyun static int ad5686_write_raw(struct iio_dev *indio_dev,
147*4882a593Smuzhiyun 			    struct iio_chan_spec const *chan,
148*4882a593Smuzhiyun 			    int val,
149*4882a593Smuzhiyun 			    int val2,
150*4882a593Smuzhiyun 			    long mask)
151*4882a593Smuzhiyun {
152*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
153*4882a593Smuzhiyun 	int ret;
154*4882a593Smuzhiyun 
155*4882a593Smuzhiyun 	switch (mask) {
156*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
157*4882a593Smuzhiyun 		if (val > (1 << chan->scan_type.realbits) || val < 0)
158*4882a593Smuzhiyun 			return -EINVAL;
159*4882a593Smuzhiyun 
160*4882a593Smuzhiyun 		mutex_lock(&st->lock);
161*4882a593Smuzhiyun 		ret = st->write(st,
162*4882a593Smuzhiyun 				AD5686_CMD_WRITE_INPUT_N_UPDATE_N,
163*4882a593Smuzhiyun 				chan->address,
164*4882a593Smuzhiyun 				val << chan->scan_type.shift);
165*4882a593Smuzhiyun 		mutex_unlock(&st->lock);
166*4882a593Smuzhiyun 		break;
167*4882a593Smuzhiyun 	default:
168*4882a593Smuzhiyun 		ret = -EINVAL;
169*4882a593Smuzhiyun 	}
170*4882a593Smuzhiyun 
171*4882a593Smuzhiyun 	return ret;
172*4882a593Smuzhiyun }
173*4882a593Smuzhiyun 
174*4882a593Smuzhiyun static const struct iio_info ad5686_info = {
175*4882a593Smuzhiyun 	.read_raw = ad5686_read_raw,
176*4882a593Smuzhiyun 	.write_raw = ad5686_write_raw,
177*4882a593Smuzhiyun };
178*4882a593Smuzhiyun 
179*4882a593Smuzhiyun static const struct iio_chan_spec_ext_info ad5686_ext_info[] = {
180*4882a593Smuzhiyun 	{
181*4882a593Smuzhiyun 		.name = "powerdown",
182*4882a593Smuzhiyun 		.read = ad5686_read_dac_powerdown,
183*4882a593Smuzhiyun 		.write = ad5686_write_dac_powerdown,
184*4882a593Smuzhiyun 		.shared = IIO_SEPARATE,
185*4882a593Smuzhiyun 	},
186*4882a593Smuzhiyun 	IIO_ENUM("powerdown_mode", IIO_SEPARATE, &ad5686_powerdown_mode_enum),
187*4882a593Smuzhiyun 	IIO_ENUM_AVAILABLE("powerdown_mode", &ad5686_powerdown_mode_enum),
188*4882a593Smuzhiyun 	{ },
189*4882a593Smuzhiyun };
190*4882a593Smuzhiyun 
191*4882a593Smuzhiyun #define AD5868_CHANNEL(chan, addr, bits, _shift) {		\
192*4882a593Smuzhiyun 		.type = IIO_VOLTAGE,				\
193*4882a593Smuzhiyun 		.indexed = 1,					\
194*4882a593Smuzhiyun 		.output = 1,					\
195*4882a593Smuzhiyun 		.channel = chan,				\
196*4882a593Smuzhiyun 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
197*4882a593Smuzhiyun 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),\
198*4882a593Smuzhiyun 		.address = addr,				\
199*4882a593Smuzhiyun 		.scan_type = {					\
200*4882a593Smuzhiyun 			.sign = 'u',				\
201*4882a593Smuzhiyun 			.realbits = (bits),			\
202*4882a593Smuzhiyun 			.storagebits = 16,			\
203*4882a593Smuzhiyun 			.shift = (_shift),			\
204*4882a593Smuzhiyun 		},						\
205*4882a593Smuzhiyun 		.ext_info = ad5686_ext_info,			\
206*4882a593Smuzhiyun }
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun #define DECLARE_AD5693_CHANNELS(name, bits, _shift)		\
209*4882a593Smuzhiyun static const struct iio_chan_spec name[] = {			\
210*4882a593Smuzhiyun 		AD5868_CHANNEL(0, 0, bits, _shift),		\
211*4882a593Smuzhiyun }
212*4882a593Smuzhiyun 
213*4882a593Smuzhiyun #define DECLARE_AD5686_CHANNELS(name, bits, _shift)		\
214*4882a593Smuzhiyun static const struct iio_chan_spec name[] = {			\
215*4882a593Smuzhiyun 		AD5868_CHANNEL(0, 1, bits, _shift),		\
216*4882a593Smuzhiyun 		AD5868_CHANNEL(1, 2, bits, _shift),		\
217*4882a593Smuzhiyun 		AD5868_CHANNEL(2, 4, bits, _shift),		\
218*4882a593Smuzhiyun 		AD5868_CHANNEL(3, 8, bits, _shift),		\
219*4882a593Smuzhiyun }
220*4882a593Smuzhiyun 
221*4882a593Smuzhiyun #define DECLARE_AD5676_CHANNELS(name, bits, _shift)		\
222*4882a593Smuzhiyun static const struct iio_chan_spec name[] = {			\
223*4882a593Smuzhiyun 		AD5868_CHANNEL(0, 0, bits, _shift),		\
224*4882a593Smuzhiyun 		AD5868_CHANNEL(1, 1, bits, _shift),		\
225*4882a593Smuzhiyun 		AD5868_CHANNEL(2, 2, bits, _shift),		\
226*4882a593Smuzhiyun 		AD5868_CHANNEL(3, 3, bits, _shift),		\
227*4882a593Smuzhiyun 		AD5868_CHANNEL(4, 4, bits, _shift),		\
228*4882a593Smuzhiyun 		AD5868_CHANNEL(5, 5, bits, _shift),		\
229*4882a593Smuzhiyun 		AD5868_CHANNEL(6, 6, bits, _shift),		\
230*4882a593Smuzhiyun 		AD5868_CHANNEL(7, 7, bits, _shift),		\
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
233*4882a593Smuzhiyun #define DECLARE_AD5679_CHANNELS(name, bits, _shift)		\
234*4882a593Smuzhiyun static const struct iio_chan_spec name[] = {			\
235*4882a593Smuzhiyun 		AD5868_CHANNEL(0, 0, bits, _shift),		\
236*4882a593Smuzhiyun 		AD5868_CHANNEL(1, 1, bits, _shift),		\
237*4882a593Smuzhiyun 		AD5868_CHANNEL(2, 2, bits, _shift),		\
238*4882a593Smuzhiyun 		AD5868_CHANNEL(3, 3, bits, _shift),		\
239*4882a593Smuzhiyun 		AD5868_CHANNEL(4, 4, bits, _shift),		\
240*4882a593Smuzhiyun 		AD5868_CHANNEL(5, 5, bits, _shift),		\
241*4882a593Smuzhiyun 		AD5868_CHANNEL(6, 6, bits, _shift),		\
242*4882a593Smuzhiyun 		AD5868_CHANNEL(7, 7, bits, _shift),		\
243*4882a593Smuzhiyun 		AD5868_CHANNEL(8, 8, bits, _shift),		\
244*4882a593Smuzhiyun 		AD5868_CHANNEL(9, 9, bits, _shift),		\
245*4882a593Smuzhiyun 		AD5868_CHANNEL(10, 10, bits, _shift),		\
246*4882a593Smuzhiyun 		AD5868_CHANNEL(11, 11, bits, _shift),		\
247*4882a593Smuzhiyun 		AD5868_CHANNEL(12, 12, bits, _shift),		\
248*4882a593Smuzhiyun 		AD5868_CHANNEL(13, 13, bits, _shift),		\
249*4882a593Smuzhiyun 		AD5868_CHANNEL(14, 14, bits, _shift),		\
250*4882a593Smuzhiyun 		AD5868_CHANNEL(15, 15, bits, _shift),		\
251*4882a593Smuzhiyun }
252*4882a593Smuzhiyun 
253*4882a593Smuzhiyun DECLARE_AD5693_CHANNELS(ad5310r_channels, 10, 2);
254*4882a593Smuzhiyun DECLARE_AD5693_CHANNELS(ad5311r_channels, 10, 6);
255*4882a593Smuzhiyun DECLARE_AD5676_CHANNELS(ad5672_channels, 12, 4);
256*4882a593Smuzhiyun DECLARE_AD5679_CHANNELS(ad5674r_channels, 12, 4);
257*4882a593Smuzhiyun DECLARE_AD5676_CHANNELS(ad5676_channels, 16, 0);
258*4882a593Smuzhiyun DECLARE_AD5679_CHANNELS(ad5679r_channels, 16, 0);
259*4882a593Smuzhiyun DECLARE_AD5686_CHANNELS(ad5684_channels, 12, 4);
260*4882a593Smuzhiyun DECLARE_AD5686_CHANNELS(ad5685r_channels, 14, 2);
261*4882a593Smuzhiyun DECLARE_AD5686_CHANNELS(ad5686_channels, 16, 0);
262*4882a593Smuzhiyun DECLARE_AD5693_CHANNELS(ad5693_channels, 16, 0);
263*4882a593Smuzhiyun DECLARE_AD5693_CHANNELS(ad5692r_channels, 14, 2);
264*4882a593Smuzhiyun DECLARE_AD5693_CHANNELS(ad5691r_channels, 12, 4);
265*4882a593Smuzhiyun 
266*4882a593Smuzhiyun static const struct ad5686_chip_info ad5686_chip_info_tbl[] = {
267*4882a593Smuzhiyun 	[ID_AD5310R] = {
268*4882a593Smuzhiyun 		.channels = ad5310r_channels,
269*4882a593Smuzhiyun 		.int_vref_mv = 2500,
270*4882a593Smuzhiyun 		.num_channels = 1,
271*4882a593Smuzhiyun 		.regmap_type = AD5310_REGMAP,
272*4882a593Smuzhiyun 	},
273*4882a593Smuzhiyun 	[ID_AD5311R] = {
274*4882a593Smuzhiyun 		.channels = ad5311r_channels,
275*4882a593Smuzhiyun 		.int_vref_mv = 2500,
276*4882a593Smuzhiyun 		.num_channels = 1,
277*4882a593Smuzhiyun 		.regmap_type = AD5693_REGMAP,
278*4882a593Smuzhiyun 	},
279*4882a593Smuzhiyun 	[ID_AD5671R] = {
280*4882a593Smuzhiyun 		.channels = ad5672_channels,
281*4882a593Smuzhiyun 		.int_vref_mv = 2500,
282*4882a593Smuzhiyun 		.num_channels = 8,
283*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
284*4882a593Smuzhiyun 	},
285*4882a593Smuzhiyun 	[ID_AD5672R] = {
286*4882a593Smuzhiyun 		.channels = ad5672_channels,
287*4882a593Smuzhiyun 		.int_vref_mv = 2500,
288*4882a593Smuzhiyun 		.num_channels = 8,
289*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
290*4882a593Smuzhiyun 	},
291*4882a593Smuzhiyun 	[ID_AD5674R] = {
292*4882a593Smuzhiyun 		.channels = ad5674r_channels,
293*4882a593Smuzhiyun 		.int_vref_mv = 2500,
294*4882a593Smuzhiyun 		.num_channels = 16,
295*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
296*4882a593Smuzhiyun 	},
297*4882a593Smuzhiyun 	[ID_AD5675R] = {
298*4882a593Smuzhiyun 		.channels = ad5676_channels,
299*4882a593Smuzhiyun 		.int_vref_mv = 2500,
300*4882a593Smuzhiyun 		.num_channels = 8,
301*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
302*4882a593Smuzhiyun 	},
303*4882a593Smuzhiyun 	[ID_AD5676] = {
304*4882a593Smuzhiyun 		.channels = ad5676_channels,
305*4882a593Smuzhiyun 		.num_channels = 8,
306*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
307*4882a593Smuzhiyun 	},
308*4882a593Smuzhiyun 	[ID_AD5676R] = {
309*4882a593Smuzhiyun 		.channels = ad5676_channels,
310*4882a593Smuzhiyun 		.int_vref_mv = 2500,
311*4882a593Smuzhiyun 		.num_channels = 8,
312*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
313*4882a593Smuzhiyun 	},
314*4882a593Smuzhiyun 	[ID_AD5679R] = {
315*4882a593Smuzhiyun 		.channels = ad5679r_channels,
316*4882a593Smuzhiyun 		.int_vref_mv = 2500,
317*4882a593Smuzhiyun 		.num_channels = 16,
318*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
319*4882a593Smuzhiyun 	},
320*4882a593Smuzhiyun 	[ID_AD5681R] = {
321*4882a593Smuzhiyun 		.channels = ad5691r_channels,
322*4882a593Smuzhiyun 		.int_vref_mv = 2500,
323*4882a593Smuzhiyun 		.num_channels = 1,
324*4882a593Smuzhiyun 		.regmap_type = AD5683_REGMAP,
325*4882a593Smuzhiyun 	},
326*4882a593Smuzhiyun 	[ID_AD5682R] = {
327*4882a593Smuzhiyun 		.channels = ad5692r_channels,
328*4882a593Smuzhiyun 		.int_vref_mv = 2500,
329*4882a593Smuzhiyun 		.num_channels = 1,
330*4882a593Smuzhiyun 		.regmap_type = AD5683_REGMAP,
331*4882a593Smuzhiyun 	},
332*4882a593Smuzhiyun 	[ID_AD5683] = {
333*4882a593Smuzhiyun 		.channels = ad5693_channels,
334*4882a593Smuzhiyun 		.num_channels = 1,
335*4882a593Smuzhiyun 		.regmap_type = AD5683_REGMAP,
336*4882a593Smuzhiyun 	},
337*4882a593Smuzhiyun 	[ID_AD5683R] = {
338*4882a593Smuzhiyun 		.channels = ad5693_channels,
339*4882a593Smuzhiyun 		.int_vref_mv = 2500,
340*4882a593Smuzhiyun 		.num_channels = 1,
341*4882a593Smuzhiyun 		.regmap_type = AD5683_REGMAP,
342*4882a593Smuzhiyun 	},
343*4882a593Smuzhiyun 	[ID_AD5684] = {
344*4882a593Smuzhiyun 		.channels = ad5684_channels,
345*4882a593Smuzhiyun 		.num_channels = 4,
346*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
347*4882a593Smuzhiyun 	},
348*4882a593Smuzhiyun 	[ID_AD5684R] = {
349*4882a593Smuzhiyun 		.channels = ad5684_channels,
350*4882a593Smuzhiyun 		.int_vref_mv = 2500,
351*4882a593Smuzhiyun 		.num_channels = 4,
352*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
353*4882a593Smuzhiyun 	},
354*4882a593Smuzhiyun 	[ID_AD5685R] = {
355*4882a593Smuzhiyun 		.channels = ad5685r_channels,
356*4882a593Smuzhiyun 		.int_vref_mv = 2500,
357*4882a593Smuzhiyun 		.num_channels = 4,
358*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
359*4882a593Smuzhiyun 	},
360*4882a593Smuzhiyun 	[ID_AD5686] = {
361*4882a593Smuzhiyun 		.channels = ad5686_channels,
362*4882a593Smuzhiyun 		.num_channels = 4,
363*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
364*4882a593Smuzhiyun 	},
365*4882a593Smuzhiyun 	[ID_AD5686R] = {
366*4882a593Smuzhiyun 		.channels = ad5686_channels,
367*4882a593Smuzhiyun 		.int_vref_mv = 2500,
368*4882a593Smuzhiyun 		.num_channels = 4,
369*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
370*4882a593Smuzhiyun 	},
371*4882a593Smuzhiyun 	[ID_AD5691R] = {
372*4882a593Smuzhiyun 		.channels = ad5691r_channels,
373*4882a593Smuzhiyun 		.int_vref_mv = 2500,
374*4882a593Smuzhiyun 		.num_channels = 1,
375*4882a593Smuzhiyun 		.regmap_type = AD5693_REGMAP,
376*4882a593Smuzhiyun 	},
377*4882a593Smuzhiyun 	[ID_AD5692R] = {
378*4882a593Smuzhiyun 		.channels = ad5692r_channels,
379*4882a593Smuzhiyun 		.int_vref_mv = 2500,
380*4882a593Smuzhiyun 		.num_channels = 1,
381*4882a593Smuzhiyun 		.regmap_type = AD5693_REGMAP,
382*4882a593Smuzhiyun 	},
383*4882a593Smuzhiyun 	[ID_AD5693] = {
384*4882a593Smuzhiyun 		.channels = ad5693_channels,
385*4882a593Smuzhiyun 		.num_channels = 1,
386*4882a593Smuzhiyun 		.regmap_type = AD5693_REGMAP,
387*4882a593Smuzhiyun 	},
388*4882a593Smuzhiyun 	[ID_AD5693R] = {
389*4882a593Smuzhiyun 		.channels = ad5693_channels,
390*4882a593Smuzhiyun 		.int_vref_mv = 2500,
391*4882a593Smuzhiyun 		.num_channels = 1,
392*4882a593Smuzhiyun 		.regmap_type = AD5693_REGMAP,
393*4882a593Smuzhiyun 	},
394*4882a593Smuzhiyun 	[ID_AD5694] = {
395*4882a593Smuzhiyun 		.channels = ad5684_channels,
396*4882a593Smuzhiyun 		.num_channels = 4,
397*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
398*4882a593Smuzhiyun 	},
399*4882a593Smuzhiyun 	[ID_AD5694R] = {
400*4882a593Smuzhiyun 		.channels = ad5684_channels,
401*4882a593Smuzhiyun 		.int_vref_mv = 2500,
402*4882a593Smuzhiyun 		.num_channels = 4,
403*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
404*4882a593Smuzhiyun 	},
405*4882a593Smuzhiyun 	[ID_AD5696] = {
406*4882a593Smuzhiyun 		.channels = ad5686_channels,
407*4882a593Smuzhiyun 		.num_channels = 4,
408*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
409*4882a593Smuzhiyun 	},
410*4882a593Smuzhiyun 	[ID_AD5696R] = {
411*4882a593Smuzhiyun 		.channels = ad5686_channels,
412*4882a593Smuzhiyun 		.int_vref_mv = 2500,
413*4882a593Smuzhiyun 		.num_channels = 4,
414*4882a593Smuzhiyun 		.regmap_type = AD5686_REGMAP,
415*4882a593Smuzhiyun 	},
416*4882a593Smuzhiyun };
417*4882a593Smuzhiyun 
ad5686_probe(struct device * dev,enum ad5686_supported_device_ids chip_type,const char * name,ad5686_write_func write,ad5686_read_func read)418*4882a593Smuzhiyun int ad5686_probe(struct device *dev,
419*4882a593Smuzhiyun 		 enum ad5686_supported_device_ids chip_type,
420*4882a593Smuzhiyun 		 const char *name, ad5686_write_func write,
421*4882a593Smuzhiyun 		 ad5686_read_func read)
422*4882a593Smuzhiyun {
423*4882a593Smuzhiyun 	struct ad5686_state *st;
424*4882a593Smuzhiyun 	struct iio_dev *indio_dev;
425*4882a593Smuzhiyun 	unsigned int val, ref_bit_msk;
426*4882a593Smuzhiyun 	u8 cmd;
427*4882a593Smuzhiyun 	int ret, i, voltage_uv = 0;
428*4882a593Smuzhiyun 
429*4882a593Smuzhiyun 	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
430*4882a593Smuzhiyun 	if (indio_dev == NULL)
431*4882a593Smuzhiyun 		return  -ENOMEM;
432*4882a593Smuzhiyun 
433*4882a593Smuzhiyun 	st = iio_priv(indio_dev);
434*4882a593Smuzhiyun 	dev_set_drvdata(dev, indio_dev);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	st->dev = dev;
437*4882a593Smuzhiyun 	st->write = write;
438*4882a593Smuzhiyun 	st->read = read;
439*4882a593Smuzhiyun 
440*4882a593Smuzhiyun 	st->reg = devm_regulator_get_optional(dev, "vcc");
441*4882a593Smuzhiyun 	if (!IS_ERR(st->reg)) {
442*4882a593Smuzhiyun 		ret = regulator_enable(st->reg);
443*4882a593Smuzhiyun 		if (ret)
444*4882a593Smuzhiyun 			return ret;
445*4882a593Smuzhiyun 
446*4882a593Smuzhiyun 		ret = regulator_get_voltage(st->reg);
447*4882a593Smuzhiyun 		if (ret < 0)
448*4882a593Smuzhiyun 			goto error_disable_reg;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 		voltage_uv = ret;
451*4882a593Smuzhiyun 	}
452*4882a593Smuzhiyun 
453*4882a593Smuzhiyun 	st->chip_info = &ad5686_chip_info_tbl[chip_type];
454*4882a593Smuzhiyun 
455*4882a593Smuzhiyun 	if (voltage_uv)
456*4882a593Smuzhiyun 		st->vref_mv = voltage_uv / 1000;
457*4882a593Smuzhiyun 	else
458*4882a593Smuzhiyun 		st->vref_mv = st->chip_info->int_vref_mv;
459*4882a593Smuzhiyun 
460*4882a593Smuzhiyun 	/* Set all the power down mode for all channels to 1K pulldown */
461*4882a593Smuzhiyun 	for (i = 0; i < st->chip_info->num_channels; i++)
462*4882a593Smuzhiyun 		st->pwr_down_mode |= (0x01 << (i * 2));
463*4882a593Smuzhiyun 
464*4882a593Smuzhiyun 	indio_dev->name = name;
465*4882a593Smuzhiyun 	indio_dev->info = &ad5686_info;
466*4882a593Smuzhiyun 	indio_dev->modes = INDIO_DIRECT_MODE;
467*4882a593Smuzhiyun 	indio_dev->channels = st->chip_info->channels;
468*4882a593Smuzhiyun 	indio_dev->num_channels = st->chip_info->num_channels;
469*4882a593Smuzhiyun 
470*4882a593Smuzhiyun 	mutex_init(&st->lock);
471*4882a593Smuzhiyun 
472*4882a593Smuzhiyun 	switch (st->chip_info->regmap_type) {
473*4882a593Smuzhiyun 	case AD5310_REGMAP:
474*4882a593Smuzhiyun 		cmd = AD5686_CMD_CONTROL_REG;
475*4882a593Smuzhiyun 		ref_bit_msk = AD5310_REF_BIT_MSK;
476*4882a593Smuzhiyun 		st->use_internal_vref = !voltage_uv;
477*4882a593Smuzhiyun 		break;
478*4882a593Smuzhiyun 	case AD5683_REGMAP:
479*4882a593Smuzhiyun 		cmd = AD5686_CMD_CONTROL_REG;
480*4882a593Smuzhiyun 		ref_bit_msk = AD5683_REF_BIT_MSK;
481*4882a593Smuzhiyun 		st->use_internal_vref = !voltage_uv;
482*4882a593Smuzhiyun 		break;
483*4882a593Smuzhiyun 	case AD5686_REGMAP:
484*4882a593Smuzhiyun 		cmd = AD5686_CMD_INTERNAL_REFER_SETUP;
485*4882a593Smuzhiyun 		ref_bit_msk = 0;
486*4882a593Smuzhiyun 		break;
487*4882a593Smuzhiyun 	case AD5693_REGMAP:
488*4882a593Smuzhiyun 		cmd = AD5686_CMD_CONTROL_REG;
489*4882a593Smuzhiyun 		ref_bit_msk = AD5693_REF_BIT_MSK;
490*4882a593Smuzhiyun 		st->use_internal_vref = !voltage_uv;
491*4882a593Smuzhiyun 		break;
492*4882a593Smuzhiyun 	default:
493*4882a593Smuzhiyun 		ret = -EINVAL;
494*4882a593Smuzhiyun 		goto error_disable_reg;
495*4882a593Smuzhiyun 	}
496*4882a593Smuzhiyun 
497*4882a593Smuzhiyun 	val = (voltage_uv | ref_bit_msk);
498*4882a593Smuzhiyun 
499*4882a593Smuzhiyun 	ret = st->write(st, cmd, 0, !!val);
500*4882a593Smuzhiyun 	if (ret)
501*4882a593Smuzhiyun 		goto error_disable_reg;
502*4882a593Smuzhiyun 
503*4882a593Smuzhiyun 	ret = iio_device_register(indio_dev);
504*4882a593Smuzhiyun 	if (ret)
505*4882a593Smuzhiyun 		goto error_disable_reg;
506*4882a593Smuzhiyun 
507*4882a593Smuzhiyun 	return 0;
508*4882a593Smuzhiyun 
509*4882a593Smuzhiyun error_disable_reg:
510*4882a593Smuzhiyun 	if (!IS_ERR(st->reg))
511*4882a593Smuzhiyun 		regulator_disable(st->reg);
512*4882a593Smuzhiyun 	return ret;
513*4882a593Smuzhiyun }
514*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad5686_probe);
515*4882a593Smuzhiyun 
ad5686_remove(struct device * dev)516*4882a593Smuzhiyun int ad5686_remove(struct device *dev)
517*4882a593Smuzhiyun {
518*4882a593Smuzhiyun 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
519*4882a593Smuzhiyun 	struct ad5686_state *st = iio_priv(indio_dev);
520*4882a593Smuzhiyun 
521*4882a593Smuzhiyun 	iio_device_unregister(indio_dev);
522*4882a593Smuzhiyun 	if (!IS_ERR(st->reg))
523*4882a593Smuzhiyun 		regulator_disable(st->reg);
524*4882a593Smuzhiyun 
525*4882a593Smuzhiyun 	return 0;
526*4882a593Smuzhiyun }
527*4882a593Smuzhiyun EXPORT_SYMBOL_GPL(ad5686_remove);
528*4882a593Smuzhiyun 
529*4882a593Smuzhiyun MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
530*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices AD5686/85/84 DAC");
531*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
532