xref: /OK3568_Linux_fs/kernel/drivers/iio/dac/ad5770r.c (revision 4882a59341e53eb6f0b4789bf948001014eff981)
1*4882a593Smuzhiyun // SPDX-License-Identifier: GPL-2.0+
2*4882a593Smuzhiyun /*
3*4882a593Smuzhiyun  * AD5770R Digital to analog converters driver
4*4882a593Smuzhiyun  *
5*4882a593Smuzhiyun  * Copyright 2018 Analog Devices Inc.
6*4882a593Smuzhiyun  */
7*4882a593Smuzhiyun 
8*4882a593Smuzhiyun #include <linux/bits.h>
9*4882a593Smuzhiyun #include <linux/delay.h>
10*4882a593Smuzhiyun #include <linux/device.h>
11*4882a593Smuzhiyun #include <linux/gpio/consumer.h>
12*4882a593Smuzhiyun #include <linux/iio/iio.h>
13*4882a593Smuzhiyun #include <linux/iio/sysfs.h>
14*4882a593Smuzhiyun #include <linux/kernel.h>
15*4882a593Smuzhiyun #include <linux/module.h>
16*4882a593Smuzhiyun #include <linux/property.h>
17*4882a593Smuzhiyun #include <linux/regmap.h>
18*4882a593Smuzhiyun #include <linux/regulator/consumer.h>
19*4882a593Smuzhiyun #include <linux/spi/spi.h>
20*4882a593Smuzhiyun 
21*4882a593Smuzhiyun #define ADI_SPI_IF_CONFIG_A		0x00
22*4882a593Smuzhiyun #define ADI_SPI_IF_CONFIG_B		0x01
23*4882a593Smuzhiyun #define ADI_SPI_IF_DEVICE_CONFIG	0x02
24*4882a593Smuzhiyun #define ADI_SPI_IF_CHIP_TYPE		0x03
25*4882a593Smuzhiyun #define ADI_SPI_IF_PRODUCT_ID_L		0x04
26*4882a593Smuzhiyun #define ADI_SPI_IF_PRODUCT_ID_H		0x05
27*4882a593Smuzhiyun #define ADI_SPI_IF_CHIP_GRADE		0x06
28*4882a593Smuzhiyun #define ADI_SPI_IF_SCRACTH_PAD		0x0A
29*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_REVISION		0x0B
30*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_VENDOR_L		0x0C
31*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_VENDOR_H		0x0D
32*4882a593Smuzhiyun #define ADI_SPI_IF_SPI_STREAM_MODE	0x0E
33*4882a593Smuzhiyun #define ADI_SPI_IF_CONFIG_C		0x10
34*4882a593Smuzhiyun #define ADI_SPI_IF_STATUS_A		0x11
35*4882a593Smuzhiyun 
36*4882a593Smuzhiyun /* ADI_SPI_IF_CONFIG_A */
37*4882a593Smuzhiyun #define ADI_SPI_IF_SW_RESET_MSK		(BIT(0) | BIT(7))
38*4882a593Smuzhiyun #define ADI_SPI_IF_SW_RESET_SEL(x)	((x) & ADI_SPI_IF_SW_RESET_MSK)
39*4882a593Smuzhiyun #define ADI_SPI_IF_ADDR_ASC_MSK		(BIT(2) | BIT(5))
40*4882a593Smuzhiyun #define ADI_SPI_IF_ADDR_ASC_SEL(x)	(((x) << 2) & ADI_SPI_IF_ADDR_ASC_MSK)
41*4882a593Smuzhiyun 
42*4882a593Smuzhiyun /* ADI_SPI_IF_CONFIG_B */
43*4882a593Smuzhiyun #define ADI_SPI_IF_SINGLE_INS_MSK	BIT(7)
44*4882a593Smuzhiyun #define ADI_SPI_IF_SINGLE_INS_SEL(x)	FIELD_PREP(ADI_SPI_IF_SINGLE_INS_MSK, x)
45*4882a593Smuzhiyun #define ADI_SPI_IF_SHORT_INS_MSK	BIT(7)
46*4882a593Smuzhiyun #define ADI_SPI_IF_SHORT_INS_SEL(x)	FIELD_PREP(ADI_SPI_IF_SINGLE_INS_MSK, x)
47*4882a593Smuzhiyun 
48*4882a593Smuzhiyun /* ADI_SPI_IF_CONFIG_C */
49*4882a593Smuzhiyun #define ADI_SPI_IF_STRICT_REG_MSK	BIT(5)
50*4882a593Smuzhiyun #define ADI_SPI_IF_STRICT_REG_GET(x)	FIELD_GET(ADI_SPI_IF_STRICT_REG_MSK, x)
51*4882a593Smuzhiyun 
52*4882a593Smuzhiyun /* AD5770R configuration registers */
53*4882a593Smuzhiyun #define AD5770R_CHANNEL_CONFIG		0x14
54*4882a593Smuzhiyun #define AD5770R_OUTPUT_RANGE(ch)	(0x15 + (ch))
55*4882a593Smuzhiyun #define AD5770R_FILTER_RESISTOR(ch)	(0x1D + (ch))
56*4882a593Smuzhiyun #define AD5770R_REFERENCE		0x1B
57*4882a593Smuzhiyun #define AD5770R_DAC_LSB(ch)		(0x26 + 2 * (ch))
58*4882a593Smuzhiyun #define AD5770R_DAC_MSB(ch)		(0x27 + 2 * (ch))
59*4882a593Smuzhiyun #define AD5770R_CH_SELECT		0x34
60*4882a593Smuzhiyun #define AD5770R_CH_ENABLE		0x44
61*4882a593Smuzhiyun 
62*4882a593Smuzhiyun /* AD5770R_CHANNEL_CONFIG */
63*4882a593Smuzhiyun #define AD5770R_CFG_CH0_SINK_EN(x)		(((x) & 0x1) << 7)
64*4882a593Smuzhiyun #define AD5770R_CFG_SHUTDOWN_B(x, ch)		(((x) & 0x1) << (ch))
65*4882a593Smuzhiyun 
66*4882a593Smuzhiyun /* AD5770R_OUTPUT_RANGE */
67*4882a593Smuzhiyun #define AD5770R_RANGE_OUTPUT_SCALING(x)		(((x) & GENMASK(5, 0)) << 2)
68*4882a593Smuzhiyun #define AD5770R_RANGE_MODE(x)			((x) & GENMASK(1, 0))
69*4882a593Smuzhiyun 
70*4882a593Smuzhiyun /* AD5770R_REFERENCE */
71*4882a593Smuzhiyun #define AD5770R_REF_RESISTOR_SEL(x)		(((x) & 0x1) << 2)
72*4882a593Smuzhiyun #define AD5770R_REF_SEL(x)			((x) & GENMASK(1, 0))
73*4882a593Smuzhiyun 
74*4882a593Smuzhiyun /* AD5770R_CH_ENABLE */
75*4882a593Smuzhiyun #define AD5770R_CH_SET(x, ch)		(((x) & 0x1) << (ch))
76*4882a593Smuzhiyun 
77*4882a593Smuzhiyun #define AD5770R_MAX_CHANNELS	6
78*4882a593Smuzhiyun #define AD5770R_MAX_CH_MODES	14
79*4882a593Smuzhiyun #define AD5770R_LOW_VREF_mV	1250
80*4882a593Smuzhiyun #define AD5770R_HIGH_VREF_mV	2500
81*4882a593Smuzhiyun 
82*4882a593Smuzhiyun enum ad5770r_ch0_modes {
83*4882a593Smuzhiyun 	AD5770R_CH0_0_300 = 0,
84*4882a593Smuzhiyun 	AD5770R_CH0_NEG_60_0,
85*4882a593Smuzhiyun 	AD5770R_CH0_NEG_60_300
86*4882a593Smuzhiyun };
87*4882a593Smuzhiyun 
88*4882a593Smuzhiyun enum ad5770r_ch1_modes {
89*4882a593Smuzhiyun 	AD5770R_CH1_0_140_LOW_HEAD = 1,
90*4882a593Smuzhiyun 	AD5770R_CH1_0_140_LOW_NOISE,
91*4882a593Smuzhiyun 	AD5770R_CH1_0_250
92*4882a593Smuzhiyun };
93*4882a593Smuzhiyun 
94*4882a593Smuzhiyun enum ad5770r_ch2_5_modes {
95*4882a593Smuzhiyun 	AD5770R_CH_LOW_RANGE = 0,
96*4882a593Smuzhiyun 	AD5770R_CH_HIGH_RANGE
97*4882a593Smuzhiyun };
98*4882a593Smuzhiyun 
99*4882a593Smuzhiyun enum ad5770r_ref_v {
100*4882a593Smuzhiyun 	AD5770R_EXT_2_5_V = 0,
101*4882a593Smuzhiyun 	AD5770R_INT_1_25_V_OUT_ON,
102*4882a593Smuzhiyun 	AD5770R_EXT_1_25_V,
103*4882a593Smuzhiyun 	AD5770R_INT_1_25_V_OUT_OFF
104*4882a593Smuzhiyun };
105*4882a593Smuzhiyun 
106*4882a593Smuzhiyun enum ad5770r_output_filter_resistor {
107*4882a593Smuzhiyun 	AD5770R_FILTER_60_OHM = 0x0,
108*4882a593Smuzhiyun 	AD5770R_FILTER_5_6_KOHM = 0x5,
109*4882a593Smuzhiyun 	AD5770R_FILTER_11_2_KOHM,
110*4882a593Smuzhiyun 	AD5770R_FILTER_22_2_KOHM,
111*4882a593Smuzhiyun 	AD5770R_FILTER_44_4_KOHM,
112*4882a593Smuzhiyun 	AD5770R_FILTER_104_KOHM,
113*4882a593Smuzhiyun };
114*4882a593Smuzhiyun 
115*4882a593Smuzhiyun struct ad5770r_out_range {
116*4882a593Smuzhiyun 	u8	out_scale;
117*4882a593Smuzhiyun 	u8	out_range_mode;
118*4882a593Smuzhiyun };
119*4882a593Smuzhiyun 
120*4882a593Smuzhiyun /**
121*4882a593Smuzhiyun  * struct ad5770R_state - driver instance specific data
122*4882a593Smuzhiyun  * @spi:		spi_device
123*4882a593Smuzhiyun  * @regmap:		regmap
124*4882a593Smuzhiyun  * @vref_reg:		fixed regulator for reference configuration
125*4882a593Smuzhiyun  * @gpio_reset:		gpio descriptor
126*4882a593Smuzhiyun  * @output_mode:	array contains channels output ranges
127*4882a593Smuzhiyun  * @vref:		reference value
128*4882a593Smuzhiyun  * @ch_pwr_down:	powerdown flags
129*4882a593Smuzhiyun  * @internal_ref:	internal reference flag
130*4882a593Smuzhiyun  * @external_res:	external 2.5k resistor flag
131*4882a593Smuzhiyun  * @transf_buf:		cache aligned buffer for spi read/write
132*4882a593Smuzhiyun  */
133*4882a593Smuzhiyun struct ad5770r_state {
134*4882a593Smuzhiyun 	struct spi_device		*spi;
135*4882a593Smuzhiyun 	struct regmap			*regmap;
136*4882a593Smuzhiyun 	struct regulator		*vref_reg;
137*4882a593Smuzhiyun 	struct gpio_desc		*gpio_reset;
138*4882a593Smuzhiyun 	struct ad5770r_out_range	output_mode[AD5770R_MAX_CHANNELS];
139*4882a593Smuzhiyun 	int				vref;
140*4882a593Smuzhiyun 	bool				ch_pwr_down[AD5770R_MAX_CHANNELS];
141*4882a593Smuzhiyun 	bool				internal_ref;
142*4882a593Smuzhiyun 	bool				external_res;
143*4882a593Smuzhiyun 	u8				transf_buf[2] ____cacheline_aligned;
144*4882a593Smuzhiyun };
145*4882a593Smuzhiyun 
146*4882a593Smuzhiyun static const struct regmap_config ad5770r_spi_regmap_config = {
147*4882a593Smuzhiyun 	.reg_bits = 8,
148*4882a593Smuzhiyun 	.val_bits = 8,
149*4882a593Smuzhiyun 	.read_flag_mask = BIT(7),
150*4882a593Smuzhiyun };
151*4882a593Smuzhiyun 
152*4882a593Smuzhiyun struct ad5770r_output_modes {
153*4882a593Smuzhiyun 	unsigned int ch;
154*4882a593Smuzhiyun 	u8 mode;
155*4882a593Smuzhiyun 	int min;
156*4882a593Smuzhiyun 	int max;
157*4882a593Smuzhiyun };
158*4882a593Smuzhiyun 
159*4882a593Smuzhiyun static struct ad5770r_output_modes ad5770r_rng_tbl[] = {
160*4882a593Smuzhiyun 	{ 0, AD5770R_CH0_0_300, 0, 300 },
161*4882a593Smuzhiyun 	{ 0, AD5770R_CH0_NEG_60_0, -60, 0 },
162*4882a593Smuzhiyun 	{ 0, AD5770R_CH0_NEG_60_300, -60, 300 },
163*4882a593Smuzhiyun 	{ 1, AD5770R_CH1_0_140_LOW_HEAD, 0, 140 },
164*4882a593Smuzhiyun 	{ 1, AD5770R_CH1_0_140_LOW_NOISE, 0, 140 },
165*4882a593Smuzhiyun 	{ 1, AD5770R_CH1_0_250, 0, 250 },
166*4882a593Smuzhiyun 	{ 2, AD5770R_CH_LOW_RANGE, 0, 55 },
167*4882a593Smuzhiyun 	{ 2, AD5770R_CH_HIGH_RANGE, 0, 150 },
168*4882a593Smuzhiyun 	{ 3, AD5770R_CH_LOW_RANGE, 0, 45 },
169*4882a593Smuzhiyun 	{ 3, AD5770R_CH_HIGH_RANGE, 0, 100 },
170*4882a593Smuzhiyun 	{ 4, AD5770R_CH_LOW_RANGE, 0, 45 },
171*4882a593Smuzhiyun 	{ 4, AD5770R_CH_HIGH_RANGE, 0, 100 },
172*4882a593Smuzhiyun 	{ 5, AD5770R_CH_LOW_RANGE, 0, 45 },
173*4882a593Smuzhiyun 	{ 5, AD5770R_CH_HIGH_RANGE, 0, 100 },
174*4882a593Smuzhiyun };
175*4882a593Smuzhiyun 
176*4882a593Smuzhiyun static const unsigned int ad5770r_filter_freqs[] = {
177*4882a593Smuzhiyun 	153, 357, 715, 1400, 2800, 262000,
178*4882a593Smuzhiyun };
179*4882a593Smuzhiyun 
180*4882a593Smuzhiyun static const unsigned int ad5770r_filter_reg_vals[] = {
181*4882a593Smuzhiyun 	AD5770R_FILTER_104_KOHM,
182*4882a593Smuzhiyun 	AD5770R_FILTER_44_4_KOHM,
183*4882a593Smuzhiyun 	AD5770R_FILTER_22_2_KOHM,
184*4882a593Smuzhiyun 	AD5770R_FILTER_11_2_KOHM,
185*4882a593Smuzhiyun 	AD5770R_FILTER_5_6_KOHM,
186*4882a593Smuzhiyun 	AD5770R_FILTER_60_OHM
187*4882a593Smuzhiyun };
188*4882a593Smuzhiyun 
ad5770r_set_output_mode(struct ad5770r_state * st,const struct ad5770r_out_range * out_mode,int channel)189*4882a593Smuzhiyun static int ad5770r_set_output_mode(struct ad5770r_state *st,
190*4882a593Smuzhiyun 				   const struct ad5770r_out_range *out_mode,
191*4882a593Smuzhiyun 				   int channel)
192*4882a593Smuzhiyun {
193*4882a593Smuzhiyun 	unsigned int regval;
194*4882a593Smuzhiyun 
195*4882a593Smuzhiyun 	regval = AD5770R_RANGE_OUTPUT_SCALING(out_mode->out_scale) |
196*4882a593Smuzhiyun 		 AD5770R_RANGE_MODE(out_mode->out_range_mode);
197*4882a593Smuzhiyun 
198*4882a593Smuzhiyun 	return regmap_write(st->regmap,
199*4882a593Smuzhiyun 			    AD5770R_OUTPUT_RANGE(channel), regval);
200*4882a593Smuzhiyun }
201*4882a593Smuzhiyun 
ad5770r_set_reference(struct ad5770r_state * st)202*4882a593Smuzhiyun static int ad5770r_set_reference(struct ad5770r_state *st)
203*4882a593Smuzhiyun {
204*4882a593Smuzhiyun 	unsigned int regval;
205*4882a593Smuzhiyun 
206*4882a593Smuzhiyun 	regval = AD5770R_REF_RESISTOR_SEL(st->external_res);
207*4882a593Smuzhiyun 
208*4882a593Smuzhiyun 	if (st->internal_ref) {
209*4882a593Smuzhiyun 		regval |= AD5770R_REF_SEL(AD5770R_INT_1_25_V_OUT_OFF);
210*4882a593Smuzhiyun 	} else {
211*4882a593Smuzhiyun 		switch (st->vref) {
212*4882a593Smuzhiyun 		case AD5770R_LOW_VREF_mV:
213*4882a593Smuzhiyun 			regval |= AD5770R_REF_SEL(AD5770R_EXT_1_25_V);
214*4882a593Smuzhiyun 			break;
215*4882a593Smuzhiyun 		case AD5770R_HIGH_VREF_mV:
216*4882a593Smuzhiyun 			regval |= AD5770R_REF_SEL(AD5770R_EXT_2_5_V);
217*4882a593Smuzhiyun 			break;
218*4882a593Smuzhiyun 		default:
219*4882a593Smuzhiyun 			regval = AD5770R_REF_SEL(AD5770R_INT_1_25_V_OUT_OFF);
220*4882a593Smuzhiyun 			break;
221*4882a593Smuzhiyun 		}
222*4882a593Smuzhiyun 	}
223*4882a593Smuzhiyun 
224*4882a593Smuzhiyun 	return regmap_write(st->regmap, AD5770R_REFERENCE, regval);
225*4882a593Smuzhiyun }
226*4882a593Smuzhiyun 
ad5770r_soft_reset(struct ad5770r_state * st)227*4882a593Smuzhiyun static int ad5770r_soft_reset(struct ad5770r_state *st)
228*4882a593Smuzhiyun {
229*4882a593Smuzhiyun 	return regmap_write(st->regmap, ADI_SPI_IF_CONFIG_A,
230*4882a593Smuzhiyun 			    ADI_SPI_IF_SW_RESET_SEL(1));
231*4882a593Smuzhiyun }
232*4882a593Smuzhiyun 
ad5770r_reset(struct ad5770r_state * st)233*4882a593Smuzhiyun static int ad5770r_reset(struct ad5770r_state *st)
234*4882a593Smuzhiyun {
235*4882a593Smuzhiyun 	/* Perform software reset if no GPIO provided */
236*4882a593Smuzhiyun 	if (!st->gpio_reset)
237*4882a593Smuzhiyun 		return ad5770r_soft_reset(st);
238*4882a593Smuzhiyun 
239*4882a593Smuzhiyun 	gpiod_set_value_cansleep(st->gpio_reset, 0);
240*4882a593Smuzhiyun 	usleep_range(10, 20);
241*4882a593Smuzhiyun 	gpiod_set_value_cansleep(st->gpio_reset, 1);
242*4882a593Smuzhiyun 
243*4882a593Smuzhiyun 	/* data must not be written during reset timeframe */
244*4882a593Smuzhiyun 	usleep_range(100, 200);
245*4882a593Smuzhiyun 
246*4882a593Smuzhiyun 	return 0;
247*4882a593Smuzhiyun }
248*4882a593Smuzhiyun 
ad5770r_get_range(struct ad5770r_state * st,int ch,int * min,int * max)249*4882a593Smuzhiyun static int ad5770r_get_range(struct ad5770r_state *st,
250*4882a593Smuzhiyun 			     int ch, int *min, int *max)
251*4882a593Smuzhiyun {
252*4882a593Smuzhiyun 	int i;
253*4882a593Smuzhiyun 	u8 tbl_ch, tbl_mode, out_range;
254*4882a593Smuzhiyun 
255*4882a593Smuzhiyun 	out_range = st->output_mode[ch].out_range_mode;
256*4882a593Smuzhiyun 
257*4882a593Smuzhiyun 	for (i = 0; i < AD5770R_MAX_CH_MODES; i++) {
258*4882a593Smuzhiyun 		tbl_ch = ad5770r_rng_tbl[i].ch;
259*4882a593Smuzhiyun 		tbl_mode = ad5770r_rng_tbl[i].mode;
260*4882a593Smuzhiyun 		if (tbl_ch == ch && tbl_mode == out_range) {
261*4882a593Smuzhiyun 			*min = ad5770r_rng_tbl[i].min;
262*4882a593Smuzhiyun 			*max = ad5770r_rng_tbl[i].max;
263*4882a593Smuzhiyun 			return 0;
264*4882a593Smuzhiyun 		}
265*4882a593Smuzhiyun 	}
266*4882a593Smuzhiyun 
267*4882a593Smuzhiyun 	return -EINVAL;
268*4882a593Smuzhiyun }
269*4882a593Smuzhiyun 
ad5770r_get_filter_freq(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,int * freq)270*4882a593Smuzhiyun static int ad5770r_get_filter_freq(struct iio_dev *indio_dev,
271*4882a593Smuzhiyun 				   const struct iio_chan_spec *chan, int *freq)
272*4882a593Smuzhiyun {
273*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
274*4882a593Smuzhiyun 	int ret;
275*4882a593Smuzhiyun 	unsigned int regval, i;
276*4882a593Smuzhiyun 
277*4882a593Smuzhiyun 	ret = regmap_read(st->regmap,
278*4882a593Smuzhiyun 			  AD5770R_FILTER_RESISTOR(chan->channel), &regval);
279*4882a593Smuzhiyun 	if (ret < 0)
280*4882a593Smuzhiyun 		return ret;
281*4882a593Smuzhiyun 
282*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ad5770r_filter_reg_vals); i++)
283*4882a593Smuzhiyun 		if (regval == ad5770r_filter_reg_vals[i])
284*4882a593Smuzhiyun 			break;
285*4882a593Smuzhiyun 	if (i == ARRAY_SIZE(ad5770r_filter_reg_vals))
286*4882a593Smuzhiyun 		return -EINVAL;
287*4882a593Smuzhiyun 
288*4882a593Smuzhiyun 	*freq = ad5770r_filter_freqs[i];
289*4882a593Smuzhiyun 
290*4882a593Smuzhiyun 	return IIO_VAL_INT;
291*4882a593Smuzhiyun }
292*4882a593Smuzhiyun 
ad5770r_set_filter_freq(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,unsigned int freq)293*4882a593Smuzhiyun static int ad5770r_set_filter_freq(struct iio_dev *indio_dev,
294*4882a593Smuzhiyun 				   const struct iio_chan_spec *chan,
295*4882a593Smuzhiyun 				   unsigned int freq)
296*4882a593Smuzhiyun {
297*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
298*4882a593Smuzhiyun 	unsigned int regval, i;
299*4882a593Smuzhiyun 
300*4882a593Smuzhiyun 	for (i = 0; i < ARRAY_SIZE(ad5770r_filter_freqs); i++)
301*4882a593Smuzhiyun 		if (ad5770r_filter_freqs[i] >= freq)
302*4882a593Smuzhiyun 			break;
303*4882a593Smuzhiyun 	if (i == ARRAY_SIZE(ad5770r_filter_freqs))
304*4882a593Smuzhiyun 		return -EINVAL;
305*4882a593Smuzhiyun 
306*4882a593Smuzhiyun 	regval = ad5770r_filter_reg_vals[i];
307*4882a593Smuzhiyun 
308*4882a593Smuzhiyun 	return regmap_write(st->regmap, AD5770R_FILTER_RESISTOR(chan->channel),
309*4882a593Smuzhiyun 			    regval);
310*4882a593Smuzhiyun }
311*4882a593Smuzhiyun 
ad5770r_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)312*4882a593Smuzhiyun static int ad5770r_read_raw(struct iio_dev *indio_dev,
313*4882a593Smuzhiyun 			    struct iio_chan_spec const *chan,
314*4882a593Smuzhiyun 			    int *val, int *val2, long info)
315*4882a593Smuzhiyun {
316*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
317*4882a593Smuzhiyun 	int max, min, ret;
318*4882a593Smuzhiyun 	u16 buf16;
319*4882a593Smuzhiyun 
320*4882a593Smuzhiyun 	switch (info) {
321*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
322*4882a593Smuzhiyun 		ret = regmap_bulk_read(st->regmap,
323*4882a593Smuzhiyun 				       chan->address,
324*4882a593Smuzhiyun 				       st->transf_buf, 2);
325*4882a593Smuzhiyun 		if (ret)
326*4882a593Smuzhiyun 			return 0;
327*4882a593Smuzhiyun 
328*4882a593Smuzhiyun 		buf16 = st->transf_buf[0] + (st->transf_buf[1] << 8);
329*4882a593Smuzhiyun 		*val = buf16 >> 2;
330*4882a593Smuzhiyun 		return IIO_VAL_INT;
331*4882a593Smuzhiyun 	case IIO_CHAN_INFO_SCALE:
332*4882a593Smuzhiyun 		ret = ad5770r_get_range(st, chan->channel, &min, &max);
333*4882a593Smuzhiyun 		if (ret < 0)
334*4882a593Smuzhiyun 			return ret;
335*4882a593Smuzhiyun 		*val = max - min;
336*4882a593Smuzhiyun 		/* There is no sign bit. (negative current is mapped from 0)
337*4882a593Smuzhiyun 		 * (sourced/sinked) current = raw * scale + offset
338*4882a593Smuzhiyun 		 * where offset in case of CH0 can be negative.
339*4882a593Smuzhiyun 		 */
340*4882a593Smuzhiyun 		*val2 = 14;
341*4882a593Smuzhiyun 		return IIO_VAL_FRACTIONAL_LOG2;
342*4882a593Smuzhiyun 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
343*4882a593Smuzhiyun 		return ad5770r_get_filter_freq(indio_dev, chan, val);
344*4882a593Smuzhiyun 	case IIO_CHAN_INFO_OFFSET:
345*4882a593Smuzhiyun 		ret = ad5770r_get_range(st, chan->channel, &min, &max);
346*4882a593Smuzhiyun 		if (ret < 0)
347*4882a593Smuzhiyun 			return ret;
348*4882a593Smuzhiyun 		*val = min;
349*4882a593Smuzhiyun 		return IIO_VAL_INT;
350*4882a593Smuzhiyun 	default:
351*4882a593Smuzhiyun 		return -EINVAL;
352*4882a593Smuzhiyun 	}
353*4882a593Smuzhiyun }
354*4882a593Smuzhiyun 
ad5770r_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)355*4882a593Smuzhiyun static int ad5770r_write_raw(struct iio_dev *indio_dev,
356*4882a593Smuzhiyun 			     struct iio_chan_spec const *chan,
357*4882a593Smuzhiyun 			     int val, int val2, long info)
358*4882a593Smuzhiyun {
359*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
360*4882a593Smuzhiyun 
361*4882a593Smuzhiyun 	switch (info) {
362*4882a593Smuzhiyun 	case IIO_CHAN_INFO_RAW:
363*4882a593Smuzhiyun 		st->transf_buf[0] = ((u16)val >> 6);
364*4882a593Smuzhiyun 		st->transf_buf[1] = (val & GENMASK(5, 0)) << 2;
365*4882a593Smuzhiyun 		return regmap_bulk_write(st->regmap, chan->address,
366*4882a593Smuzhiyun 					 st->transf_buf, 2);
367*4882a593Smuzhiyun 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
368*4882a593Smuzhiyun 		return ad5770r_set_filter_freq(indio_dev, chan, val);
369*4882a593Smuzhiyun 	default:
370*4882a593Smuzhiyun 		return -EINVAL;
371*4882a593Smuzhiyun 	}
372*4882a593Smuzhiyun }
373*4882a593Smuzhiyun 
ad5770r_read_freq_avail(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,const int ** vals,int * type,int * length,long mask)374*4882a593Smuzhiyun static int ad5770r_read_freq_avail(struct iio_dev *indio_dev,
375*4882a593Smuzhiyun 				   struct iio_chan_spec const *chan,
376*4882a593Smuzhiyun 				   const int **vals, int *type, int *length,
377*4882a593Smuzhiyun 				   long mask)
378*4882a593Smuzhiyun {
379*4882a593Smuzhiyun 	switch (mask) {
380*4882a593Smuzhiyun 	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
381*4882a593Smuzhiyun 		*type = IIO_VAL_INT;
382*4882a593Smuzhiyun 		*vals = ad5770r_filter_freqs;
383*4882a593Smuzhiyun 		*length = ARRAY_SIZE(ad5770r_filter_freqs);
384*4882a593Smuzhiyun 		return IIO_AVAIL_LIST;
385*4882a593Smuzhiyun 	}
386*4882a593Smuzhiyun 
387*4882a593Smuzhiyun 	return -EINVAL;
388*4882a593Smuzhiyun }
389*4882a593Smuzhiyun 
ad5770r_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)390*4882a593Smuzhiyun static int ad5770r_reg_access(struct iio_dev *indio_dev,
391*4882a593Smuzhiyun 			      unsigned int reg,
392*4882a593Smuzhiyun 			      unsigned int writeval,
393*4882a593Smuzhiyun 			      unsigned int *readval)
394*4882a593Smuzhiyun {
395*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
396*4882a593Smuzhiyun 
397*4882a593Smuzhiyun 	if (readval)
398*4882a593Smuzhiyun 		return regmap_read(st->regmap, reg, readval);
399*4882a593Smuzhiyun 	else
400*4882a593Smuzhiyun 		return regmap_write(st->regmap, reg, writeval);
401*4882a593Smuzhiyun }
402*4882a593Smuzhiyun 
403*4882a593Smuzhiyun static const struct iio_info ad5770r_info = {
404*4882a593Smuzhiyun 	.read_raw = ad5770r_read_raw,
405*4882a593Smuzhiyun 	.write_raw = ad5770r_write_raw,
406*4882a593Smuzhiyun 	.read_avail = ad5770r_read_freq_avail,
407*4882a593Smuzhiyun 	.debugfs_reg_access = &ad5770r_reg_access,
408*4882a593Smuzhiyun };
409*4882a593Smuzhiyun 
ad5770r_store_output_range(struct ad5770r_state * st,int min,int max,int index)410*4882a593Smuzhiyun static int ad5770r_store_output_range(struct ad5770r_state *st,
411*4882a593Smuzhiyun 				      int min, int max, int index)
412*4882a593Smuzhiyun {
413*4882a593Smuzhiyun 	int i;
414*4882a593Smuzhiyun 
415*4882a593Smuzhiyun 	for (i = 0; i < AD5770R_MAX_CH_MODES; i++) {
416*4882a593Smuzhiyun 		if (ad5770r_rng_tbl[i].ch != index)
417*4882a593Smuzhiyun 			continue;
418*4882a593Smuzhiyun 		if (ad5770r_rng_tbl[i].min != min ||
419*4882a593Smuzhiyun 		    ad5770r_rng_tbl[i].max != max)
420*4882a593Smuzhiyun 			continue;
421*4882a593Smuzhiyun 		st->output_mode[index].out_range_mode = ad5770r_rng_tbl[i].mode;
422*4882a593Smuzhiyun 
423*4882a593Smuzhiyun 		return 0;
424*4882a593Smuzhiyun 	}
425*4882a593Smuzhiyun 
426*4882a593Smuzhiyun 	return -EINVAL;
427*4882a593Smuzhiyun }
428*4882a593Smuzhiyun 
ad5770r_read_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,char * buf)429*4882a593Smuzhiyun static ssize_t ad5770r_read_dac_powerdown(struct iio_dev *indio_dev,
430*4882a593Smuzhiyun 					  uintptr_t private,
431*4882a593Smuzhiyun 					  const struct iio_chan_spec *chan,
432*4882a593Smuzhiyun 					  char *buf)
433*4882a593Smuzhiyun {
434*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
435*4882a593Smuzhiyun 
436*4882a593Smuzhiyun 	return sprintf(buf, "%d\n", st->ch_pwr_down[chan->channel]);
437*4882a593Smuzhiyun }
438*4882a593Smuzhiyun 
ad5770r_write_dac_powerdown(struct iio_dev * indio_dev,uintptr_t private,const struct iio_chan_spec * chan,const char * buf,size_t len)439*4882a593Smuzhiyun static ssize_t ad5770r_write_dac_powerdown(struct iio_dev *indio_dev,
440*4882a593Smuzhiyun 					   uintptr_t private,
441*4882a593Smuzhiyun 					   const struct iio_chan_spec *chan,
442*4882a593Smuzhiyun 					   const char *buf, size_t len)
443*4882a593Smuzhiyun {
444*4882a593Smuzhiyun 	struct ad5770r_state *st = iio_priv(indio_dev);
445*4882a593Smuzhiyun 	unsigned int regval;
446*4882a593Smuzhiyun 	unsigned int mask;
447*4882a593Smuzhiyun 	bool readin;
448*4882a593Smuzhiyun 	int ret;
449*4882a593Smuzhiyun 
450*4882a593Smuzhiyun 	ret = kstrtobool(buf, &readin);
451*4882a593Smuzhiyun 	if (ret)
452*4882a593Smuzhiyun 		return ret;
453*4882a593Smuzhiyun 
454*4882a593Smuzhiyun 	readin = !readin;
455*4882a593Smuzhiyun 
456*4882a593Smuzhiyun 	regval = AD5770R_CFG_SHUTDOWN_B(readin, chan->channel);
457*4882a593Smuzhiyun 	if (chan->channel == 0 &&
458*4882a593Smuzhiyun 	    st->output_mode[0].out_range_mode > AD5770R_CH0_0_300) {
459*4882a593Smuzhiyun 		regval |= AD5770R_CFG_CH0_SINK_EN(readin);
460*4882a593Smuzhiyun 		mask = BIT(chan->channel) + BIT(7);
461*4882a593Smuzhiyun 	} else {
462*4882a593Smuzhiyun 		mask = BIT(chan->channel);
463*4882a593Smuzhiyun 	}
464*4882a593Smuzhiyun 	ret = regmap_update_bits(st->regmap, AD5770R_CHANNEL_CONFIG, mask,
465*4882a593Smuzhiyun 				 regval);
466*4882a593Smuzhiyun 	if (ret)
467*4882a593Smuzhiyun 		return ret;
468*4882a593Smuzhiyun 
469*4882a593Smuzhiyun 	regval = AD5770R_CH_SET(readin, chan->channel);
470*4882a593Smuzhiyun 	ret = regmap_update_bits(st->regmap, AD5770R_CH_ENABLE,
471*4882a593Smuzhiyun 				 BIT(chan->channel), regval);
472*4882a593Smuzhiyun 	if (ret)
473*4882a593Smuzhiyun 		return ret;
474*4882a593Smuzhiyun 
475*4882a593Smuzhiyun 	st->ch_pwr_down[chan->channel] = !readin;
476*4882a593Smuzhiyun 
477*4882a593Smuzhiyun 	return len;
478*4882a593Smuzhiyun }
479*4882a593Smuzhiyun 
480*4882a593Smuzhiyun static const struct iio_chan_spec_ext_info ad5770r_ext_info[] = {
481*4882a593Smuzhiyun 	{
482*4882a593Smuzhiyun 		.name = "powerdown",
483*4882a593Smuzhiyun 		.read = ad5770r_read_dac_powerdown,
484*4882a593Smuzhiyun 		.write = ad5770r_write_dac_powerdown,
485*4882a593Smuzhiyun 		.shared = IIO_SEPARATE,
486*4882a593Smuzhiyun 	},
487*4882a593Smuzhiyun 	{ }
488*4882a593Smuzhiyun };
489*4882a593Smuzhiyun 
490*4882a593Smuzhiyun #define AD5770R_IDAC_CHANNEL(index, reg) {				\
491*4882a593Smuzhiyun 	.type = IIO_CURRENT,						\
492*4882a593Smuzhiyun 	.address = reg,							\
493*4882a593Smuzhiyun 	.indexed = 1,							\
494*4882a593Smuzhiyun 	.channel = index,						\
495*4882a593Smuzhiyun 	.output = 1,							\
496*4882a593Smuzhiyun 	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |			\
497*4882a593Smuzhiyun 		BIT(IIO_CHAN_INFO_SCALE) |				\
498*4882a593Smuzhiyun 		BIT(IIO_CHAN_INFO_OFFSET) |				\
499*4882a593Smuzhiyun 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),	\
500*4882a593Smuzhiyun 	.info_mask_shared_by_type_available =				\
501*4882a593Smuzhiyun 		BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),	\
502*4882a593Smuzhiyun 	.ext_info = ad5770r_ext_info,					\
503*4882a593Smuzhiyun }
504*4882a593Smuzhiyun 
505*4882a593Smuzhiyun static const struct iio_chan_spec ad5770r_channels[] = {
506*4882a593Smuzhiyun 	AD5770R_IDAC_CHANNEL(0, AD5770R_DAC_MSB(0)),
507*4882a593Smuzhiyun 	AD5770R_IDAC_CHANNEL(1, AD5770R_DAC_MSB(1)),
508*4882a593Smuzhiyun 	AD5770R_IDAC_CHANNEL(2, AD5770R_DAC_MSB(2)),
509*4882a593Smuzhiyun 	AD5770R_IDAC_CHANNEL(3, AD5770R_DAC_MSB(3)),
510*4882a593Smuzhiyun 	AD5770R_IDAC_CHANNEL(4, AD5770R_DAC_MSB(4)),
511*4882a593Smuzhiyun 	AD5770R_IDAC_CHANNEL(5, AD5770R_DAC_MSB(5)),
512*4882a593Smuzhiyun };
513*4882a593Smuzhiyun 
ad5770r_channel_config(struct ad5770r_state * st)514*4882a593Smuzhiyun static int ad5770r_channel_config(struct ad5770r_state *st)
515*4882a593Smuzhiyun {
516*4882a593Smuzhiyun 	int ret, tmp[2], min, max;
517*4882a593Smuzhiyun 	unsigned int num;
518*4882a593Smuzhiyun 	struct fwnode_handle *child;
519*4882a593Smuzhiyun 
520*4882a593Smuzhiyun 	num = device_get_child_node_count(&st->spi->dev);
521*4882a593Smuzhiyun 	if (num != AD5770R_MAX_CHANNELS)
522*4882a593Smuzhiyun 		return -EINVAL;
523*4882a593Smuzhiyun 
524*4882a593Smuzhiyun 	device_for_each_child_node(&st->spi->dev, child) {
525*4882a593Smuzhiyun 		ret = fwnode_property_read_u32(child, "reg", &num);
526*4882a593Smuzhiyun 		if (ret)
527*4882a593Smuzhiyun 			goto err_child_out;
528*4882a593Smuzhiyun 		if (num >= AD5770R_MAX_CHANNELS) {
529*4882a593Smuzhiyun 			ret = -EINVAL;
530*4882a593Smuzhiyun 			goto err_child_out;
531*4882a593Smuzhiyun 		}
532*4882a593Smuzhiyun 
533*4882a593Smuzhiyun 		ret = fwnode_property_read_u32_array(child,
534*4882a593Smuzhiyun 						     "adi,range-microamp",
535*4882a593Smuzhiyun 						     tmp, 2);
536*4882a593Smuzhiyun 		if (ret)
537*4882a593Smuzhiyun 			goto err_child_out;
538*4882a593Smuzhiyun 
539*4882a593Smuzhiyun 		min = tmp[0] / 1000;
540*4882a593Smuzhiyun 		max = tmp[1] / 1000;
541*4882a593Smuzhiyun 		ret = ad5770r_store_output_range(st, min, max, num);
542*4882a593Smuzhiyun 		if (ret)
543*4882a593Smuzhiyun 			goto err_child_out;
544*4882a593Smuzhiyun 	}
545*4882a593Smuzhiyun 
546*4882a593Smuzhiyun 	return 0;
547*4882a593Smuzhiyun 
548*4882a593Smuzhiyun err_child_out:
549*4882a593Smuzhiyun 	fwnode_handle_put(child);
550*4882a593Smuzhiyun 	return ret;
551*4882a593Smuzhiyun }
552*4882a593Smuzhiyun 
ad5770r_init(struct ad5770r_state * st)553*4882a593Smuzhiyun static int ad5770r_init(struct ad5770r_state *st)
554*4882a593Smuzhiyun {
555*4882a593Smuzhiyun 	int ret, i;
556*4882a593Smuzhiyun 
557*4882a593Smuzhiyun 	st->gpio_reset = devm_gpiod_get_optional(&st->spi->dev, "reset",
558*4882a593Smuzhiyun 						 GPIOD_OUT_HIGH);
559*4882a593Smuzhiyun 	if (IS_ERR(st->gpio_reset))
560*4882a593Smuzhiyun 		return PTR_ERR(st->gpio_reset);
561*4882a593Smuzhiyun 
562*4882a593Smuzhiyun 	/* Perform a reset */
563*4882a593Smuzhiyun 	ret = ad5770r_reset(st);
564*4882a593Smuzhiyun 	if (ret)
565*4882a593Smuzhiyun 		return ret;
566*4882a593Smuzhiyun 
567*4882a593Smuzhiyun 	/* Set output range */
568*4882a593Smuzhiyun 	ret = ad5770r_channel_config(st);
569*4882a593Smuzhiyun 	if (ret)
570*4882a593Smuzhiyun 		return ret;
571*4882a593Smuzhiyun 
572*4882a593Smuzhiyun 	for (i = 0; i < AD5770R_MAX_CHANNELS; i++) {
573*4882a593Smuzhiyun 		ret = ad5770r_set_output_mode(st,  &st->output_mode[i], i);
574*4882a593Smuzhiyun 		if (ret)
575*4882a593Smuzhiyun 			return ret;
576*4882a593Smuzhiyun 	}
577*4882a593Smuzhiyun 
578*4882a593Smuzhiyun 	st->external_res = fwnode_property_read_bool(st->spi->dev.fwnode,
579*4882a593Smuzhiyun 						     "adi,external-resistor");
580*4882a593Smuzhiyun 
581*4882a593Smuzhiyun 	ret = ad5770r_set_reference(st);
582*4882a593Smuzhiyun 	if (ret)
583*4882a593Smuzhiyun 		return ret;
584*4882a593Smuzhiyun 
585*4882a593Smuzhiyun 	/* Set outputs off */
586*4882a593Smuzhiyun 	ret = regmap_write(st->regmap, AD5770R_CHANNEL_CONFIG, 0x00);
587*4882a593Smuzhiyun 	if (ret)
588*4882a593Smuzhiyun 		return ret;
589*4882a593Smuzhiyun 
590*4882a593Smuzhiyun 	ret = regmap_write(st->regmap, AD5770R_CH_ENABLE, 0x00);
591*4882a593Smuzhiyun 	if (ret)
592*4882a593Smuzhiyun 		return ret;
593*4882a593Smuzhiyun 
594*4882a593Smuzhiyun 	for (i = 0; i < AD5770R_MAX_CHANNELS; i++)
595*4882a593Smuzhiyun 		st->ch_pwr_down[i] = true;
596*4882a593Smuzhiyun 
597*4882a593Smuzhiyun 	return ret;
598*4882a593Smuzhiyun }
599*4882a593Smuzhiyun 
ad5770r_disable_regulator(void * data)600*4882a593Smuzhiyun static void ad5770r_disable_regulator(void *data)
601*4882a593Smuzhiyun {
602*4882a593Smuzhiyun 	struct ad5770r_state *st = data;
603*4882a593Smuzhiyun 
604*4882a593Smuzhiyun 	regulator_disable(st->vref_reg);
605*4882a593Smuzhiyun }
606*4882a593Smuzhiyun 
ad5770r_probe(struct spi_device * spi)607*4882a593Smuzhiyun static int ad5770r_probe(struct spi_device *spi)
608*4882a593Smuzhiyun {
609*4882a593Smuzhiyun 	struct ad5770r_state *st;
610*4882a593Smuzhiyun 	struct iio_dev *indio_dev;
611*4882a593Smuzhiyun 	struct regmap *regmap;
612*4882a593Smuzhiyun 	int ret;
613*4882a593Smuzhiyun 
614*4882a593Smuzhiyun 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
615*4882a593Smuzhiyun 	if (!indio_dev)
616*4882a593Smuzhiyun 		return -ENOMEM;
617*4882a593Smuzhiyun 
618*4882a593Smuzhiyun 	st = iio_priv(indio_dev);
619*4882a593Smuzhiyun 	spi_set_drvdata(spi, indio_dev);
620*4882a593Smuzhiyun 
621*4882a593Smuzhiyun 	st->spi = spi;
622*4882a593Smuzhiyun 
623*4882a593Smuzhiyun 	regmap = devm_regmap_init_spi(spi, &ad5770r_spi_regmap_config);
624*4882a593Smuzhiyun 	if (IS_ERR(regmap)) {
625*4882a593Smuzhiyun 		dev_err(&spi->dev, "Error initializing spi regmap: %ld\n",
626*4882a593Smuzhiyun 			PTR_ERR(regmap));
627*4882a593Smuzhiyun 		return PTR_ERR(regmap);
628*4882a593Smuzhiyun 	}
629*4882a593Smuzhiyun 	st->regmap = regmap;
630*4882a593Smuzhiyun 
631*4882a593Smuzhiyun 	st->vref_reg = devm_regulator_get_optional(&spi->dev, "vref");
632*4882a593Smuzhiyun 	if (!IS_ERR(st->vref_reg)) {
633*4882a593Smuzhiyun 		ret = regulator_enable(st->vref_reg);
634*4882a593Smuzhiyun 		if (ret) {
635*4882a593Smuzhiyun 			dev_err(&spi->dev,
636*4882a593Smuzhiyun 				"Failed to enable vref regulators: %d\n", ret);
637*4882a593Smuzhiyun 			return ret;
638*4882a593Smuzhiyun 		}
639*4882a593Smuzhiyun 
640*4882a593Smuzhiyun 		ret = devm_add_action_or_reset(&spi->dev,
641*4882a593Smuzhiyun 					       ad5770r_disable_regulator,
642*4882a593Smuzhiyun 					       st);
643*4882a593Smuzhiyun 		if (ret < 0)
644*4882a593Smuzhiyun 			return ret;
645*4882a593Smuzhiyun 
646*4882a593Smuzhiyun 		ret = regulator_get_voltage(st->vref_reg);
647*4882a593Smuzhiyun 		if (ret < 0)
648*4882a593Smuzhiyun 			return ret;
649*4882a593Smuzhiyun 
650*4882a593Smuzhiyun 		st->vref = ret / 1000;
651*4882a593Smuzhiyun 	} else {
652*4882a593Smuzhiyun 		if (PTR_ERR(st->vref_reg) == -ENODEV) {
653*4882a593Smuzhiyun 			st->vref = AD5770R_LOW_VREF_mV;
654*4882a593Smuzhiyun 			st->internal_ref = true;
655*4882a593Smuzhiyun 		} else {
656*4882a593Smuzhiyun 			return PTR_ERR(st->vref_reg);
657*4882a593Smuzhiyun 		}
658*4882a593Smuzhiyun 	}
659*4882a593Smuzhiyun 
660*4882a593Smuzhiyun 	indio_dev->name = spi_get_device_id(spi)->name;
661*4882a593Smuzhiyun 	indio_dev->info = &ad5770r_info;
662*4882a593Smuzhiyun 	indio_dev->modes = INDIO_DIRECT_MODE;
663*4882a593Smuzhiyun 	indio_dev->channels = ad5770r_channels;
664*4882a593Smuzhiyun 	indio_dev->num_channels = ARRAY_SIZE(ad5770r_channels);
665*4882a593Smuzhiyun 
666*4882a593Smuzhiyun 	ret = ad5770r_init(st);
667*4882a593Smuzhiyun 	if (ret < 0) {
668*4882a593Smuzhiyun 		dev_err(&spi->dev, "AD5770R init failed\n");
669*4882a593Smuzhiyun 		return ret;
670*4882a593Smuzhiyun 	}
671*4882a593Smuzhiyun 
672*4882a593Smuzhiyun 	return devm_iio_device_register(&st->spi->dev, indio_dev);
673*4882a593Smuzhiyun }
674*4882a593Smuzhiyun 
675*4882a593Smuzhiyun static const struct of_device_id ad5770r_of_id[] = {
676*4882a593Smuzhiyun 	{ .compatible = "adi,ad5770r", },
677*4882a593Smuzhiyun 	{},
678*4882a593Smuzhiyun };
679*4882a593Smuzhiyun MODULE_DEVICE_TABLE(of, ad5770r_of_id);
680*4882a593Smuzhiyun 
681*4882a593Smuzhiyun static const struct spi_device_id ad5770r_id[] = {
682*4882a593Smuzhiyun 	{ "ad5770r", 0 },
683*4882a593Smuzhiyun 	{},
684*4882a593Smuzhiyun };
685*4882a593Smuzhiyun MODULE_DEVICE_TABLE(spi, ad5770r_id);
686*4882a593Smuzhiyun 
687*4882a593Smuzhiyun static struct spi_driver ad5770r_driver = {
688*4882a593Smuzhiyun 	.driver = {
689*4882a593Smuzhiyun 		.name = KBUILD_MODNAME,
690*4882a593Smuzhiyun 		.of_match_table = ad5770r_of_id,
691*4882a593Smuzhiyun 	},
692*4882a593Smuzhiyun 	.probe = ad5770r_probe,
693*4882a593Smuzhiyun 	.id_table = ad5770r_id,
694*4882a593Smuzhiyun };
695*4882a593Smuzhiyun 
696*4882a593Smuzhiyun module_spi_driver(ad5770r_driver);
697*4882a593Smuzhiyun 
698*4882a593Smuzhiyun MODULE_AUTHOR("Mircea Caprioru <mircea.caprioru@analog.com>");
699*4882a593Smuzhiyun MODULE_DESCRIPTION("Analog Devices AD5770R IDAC");
700*4882a593Smuzhiyun MODULE_LICENSE("GPL v2");
701