xref: /linux/drivers/iio/adc/ad7779.c (revision 25768de50b1f2dbb6ea44bd5148a87fe2c9c3688)
1*c9a3f8c7SRamona Alexandra Nechita // SPDX-License-Identifier: GPL-2.0+
2*c9a3f8c7SRamona Alexandra Nechita /*
3*c9a3f8c7SRamona Alexandra Nechita  * AD7770, AD7771, AD7779 ADC
4*c9a3f8c7SRamona Alexandra Nechita  *
5*c9a3f8c7SRamona Alexandra Nechita  * Copyright 2023-2024 Analog Devices Inc.
6*c9a3f8c7SRamona Alexandra Nechita  */
7*c9a3f8c7SRamona Alexandra Nechita 
8*c9a3f8c7SRamona Alexandra Nechita #include <linux/bitfield.h>
9*c9a3f8c7SRamona Alexandra Nechita #include <linux/bitmap.h>
10*c9a3f8c7SRamona Alexandra Nechita #include <linux/clk.h>
11*c9a3f8c7SRamona Alexandra Nechita #include <linux/crc8.h>
12*c9a3f8c7SRamona Alexandra Nechita #include <linux/delay.h>
13*c9a3f8c7SRamona Alexandra Nechita #include <linux/err.h>
14*c9a3f8c7SRamona Alexandra Nechita #include <linux/gpio/consumer.h>
15*c9a3f8c7SRamona Alexandra Nechita #include <linux/interrupt.h>
16*c9a3f8c7SRamona Alexandra Nechita #include <linux/irq.h>
17*c9a3f8c7SRamona Alexandra Nechita #include <linux/math.h>
18*c9a3f8c7SRamona Alexandra Nechita #include <linux/module.h>
19*c9a3f8c7SRamona Alexandra Nechita #include <linux/mod_devicetable.h>
20*c9a3f8c7SRamona Alexandra Nechita #include <linux/regulator/consumer.h>
21*c9a3f8c7SRamona Alexandra Nechita #include <linux/spi/spi.h>
22*c9a3f8c7SRamona Alexandra Nechita #include <linux/string.h>
23*c9a3f8c7SRamona Alexandra Nechita #include <linux/types.h>
24*c9a3f8c7SRamona Alexandra Nechita #include <linux/unaligned.h>
25*c9a3f8c7SRamona Alexandra Nechita #include <linux/units.h>
26*c9a3f8c7SRamona Alexandra Nechita 
27*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/iio.h>
28*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/buffer.h>
29*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/sysfs.h>
30*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/trigger.h>
31*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/triggered_buffer.h>
32*c9a3f8c7SRamona Alexandra Nechita #include <linux/iio/trigger_consumer.h>
33*c9a3f8c7SRamona Alexandra Nechita 
34*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SPI_READ_CMD			BIT(7)
35*c9a3f8c7SRamona Alexandra Nechita 
36*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DISABLE_SD			BIT(7)
37*c9a3f8c7SRamona Alexandra Nechita 
38*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_DISABLE			0x08
39*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_SYNC_OFFSET(ch)		(0x09 + (ch))
40*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_CONFIG(ch)		(0x00 + (ch))
41*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GENERAL_USER_CONFIG_1	0x11
42*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GENERAL_USER_CONFIG_2	0x12
43*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GENERAL_USER_CONFIG_3	0x13
44*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_DOUT_FORMAT			0x14
45*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_ADC_MUX_CONFIG		0x15
46*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GPIO_CONFIG			0x17
47*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_BUFFER_CONFIG_1		0x19
48*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GLOBAL_MUX_CONFIG		0x16
49*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_BUFFER_CONFIG_2		0x1A
50*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GPIO_DATA			0x18
51*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_OFFSET_UPPER_BYTE(ch)	(0x1C + (ch) * 6)
52*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_OFFSET_LOWER_BYTE(ch)	(0x1E + (ch) * 6)
53*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_GAIN_UPPER_BYTE(ch)	(0x1F + (ch) * 6)
54*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_OFFSET_MID_BYTE(ch)	(0x1D + (ch) * 6)
55*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_GAIN_MID_BYTE(ch)		(0x20 + (ch) * 6)
56*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_ERR_REG(ch)		(0x4C + (ch))
57*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH0_1_SAT_ERR		0x54
58*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH_GAIN_LOWER_BYTE(ch)	(0x21 + (ch) * 6)
59*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH2_3_SAT_ERR		0x55
60*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH4_5_SAT_ERR		0x56
61*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CH6_7_SAT_ERR		0x57
62*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_CHX_ERR_REG_EN		0x58
63*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_1		0x59
64*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_1_EN		0x5A
65*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_2		0x5B
66*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_GEN_ERR_REG_2_EN		0x5C
67*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_STATUS_REG_1			0x5D
68*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_STATUS_REG_2			0x5E
69*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_STATUS_REG_3			0x5F
70*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_N_MSB			0x60
71*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_N_LSB			0x61
72*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_IF_MSB			0x62
73*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_IF_LSB			0x63
74*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_SRC_UPDATE			0x64
75*c9a3f8c7SRamona Alexandra Nechita 
76*c9a3f8c7SRamona Alexandra Nechita #define AD7779_FILTER_MSK			BIT(6)
77*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MOD_POWERMODE_MSK		BIT(6)
78*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MOD_PDB_REFOUT_MSK		BIT(4)
79*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MOD_SPI_EN_MSK			BIT(4)
80*c9a3f8c7SRamona Alexandra Nechita #define AD7779_USRMOD_INIT_MSK			GENMASK(6, 4)
81*c9a3f8c7SRamona Alexandra Nechita 
82*c9a3f8c7SRamona Alexandra Nechita /* AD7779_REG_DOUT_FORMAT */
83*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DOUT_FORMAT_MSK			GENMASK(7, 6)
84*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DOUT_HEADER_FORMAT		BIT(5)
85*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DCLK_CLK_DIV_MSK			GENMASK(3, 1)
86*c9a3f8c7SRamona Alexandra Nechita 
87*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REFMUX_CTRL_MSK			GENMASK(7, 6)
88*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SPI_CRC_EN_MSK			BIT(0)
89*c9a3f8c7SRamona Alexandra Nechita 
90*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MAXCLK_LOWPOWER			(4096 * HZ_PER_KHZ)
91*c9a3f8c7SRamona Alexandra Nechita #define AD7779_NUM_CHANNELS			8
92*c9a3f8c7SRamona Alexandra Nechita #define AD7779_RESET_BUF_SIZE			8
93*c9a3f8c7SRamona Alexandra Nechita #define AD7779_CHAN_DATA_SIZE			4
94*c9a3f8c7SRamona Alexandra Nechita 
95*c9a3f8c7SRamona Alexandra Nechita #define AD7779_LOWPOWER_DIV			512
96*c9a3f8c7SRamona Alexandra Nechita #define AD7779_HIGHPOWER_DIV			2048
97*c9a3f8c7SRamona Alexandra Nechita 
98*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SINC3_MAXFREQ			(16 * HZ_PER_KHZ)
99*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SINC5_MAXFREQ			(128 * HZ_PER_KHZ)
100*c9a3f8c7SRamona Alexandra Nechita 
101*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DEFAULT_SAMPLING_FREQ		(8 * HZ_PER_KHZ)
102*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DEFAULT_SAMPLING_2LINE		(4 * HZ_PER_KHZ)
103*c9a3f8c7SRamona Alexandra Nechita #define AD7779_DEFAULT_SAMPLING_1LINE		(2 * HZ_PER_KHZ)
104*c9a3f8c7SRamona Alexandra Nechita 
105*c9a3f8c7SRamona Alexandra Nechita #define AD7779_SPIMODE_MAX_SAMP_FREQ		(16 * HZ_PER_KHZ)
106*c9a3f8c7SRamona Alexandra Nechita 
107*c9a3f8c7SRamona Alexandra Nechita #define GAIN_REL				0x555555
108*c9a3f8c7SRamona Alexandra Nechita #define AD7779_FREQ_MSB_MSK			GENMASK(15, 8)
109*c9a3f8c7SRamona Alexandra Nechita #define AD7779_FREQ_LSB_MSK			GENMASK(7, 0)
110*c9a3f8c7SRamona Alexandra Nechita #define AD7779_UPPER				GENMASK(23, 16)
111*c9a3f8c7SRamona Alexandra Nechita #define AD7779_MID				GENMASK(15, 8)
112*c9a3f8c7SRamona Alexandra Nechita #define AD7779_LOWER				GENMASK(7, 0)
113*c9a3f8c7SRamona Alexandra Nechita 
114*c9a3f8c7SRamona Alexandra Nechita #define AD7779_REG_MSK		GENMASK(6, 0)
115*c9a3f8c7SRamona Alexandra Nechita 
116*c9a3f8c7SRamona Alexandra Nechita #define AD7779_CRC8_POLY			0x07
117*c9a3f8c7SRamona Alexandra Nechita DECLARE_CRC8_TABLE(ad7779_crc8_table);
118*c9a3f8c7SRamona Alexandra Nechita 
119*c9a3f8c7SRamona Alexandra Nechita enum ad7779_filter {
120*c9a3f8c7SRamona Alexandra Nechita 	AD7779_SINC3,
121*c9a3f8c7SRamona Alexandra Nechita 	AD7779_SINC5,
122*c9a3f8c7SRamona Alexandra Nechita };
123*c9a3f8c7SRamona Alexandra Nechita 
124*c9a3f8c7SRamona Alexandra Nechita enum ad7779_variant {
125*c9a3f8c7SRamona Alexandra Nechita 	ad7770,
126*c9a3f8c7SRamona Alexandra Nechita 	ad7771,
127*c9a3f8c7SRamona Alexandra Nechita 	ad7779,
128*c9a3f8c7SRamona Alexandra Nechita };
129*c9a3f8c7SRamona Alexandra Nechita 
130*c9a3f8c7SRamona Alexandra Nechita enum ad7779_power_mode {
131*c9a3f8c7SRamona Alexandra Nechita 	AD7779_LOW_POWER,
132*c9a3f8c7SRamona Alexandra Nechita 	AD7779_HIGH_POWER,
133*c9a3f8c7SRamona Alexandra Nechita };
134*c9a3f8c7SRamona Alexandra Nechita 
135*c9a3f8c7SRamona Alexandra Nechita struct ad7779_chip_info {
136*c9a3f8c7SRamona Alexandra Nechita 	const char *name;
137*c9a3f8c7SRamona Alexandra Nechita 	struct iio_chan_spec const *channels;
138*c9a3f8c7SRamona Alexandra Nechita };
139*c9a3f8c7SRamona Alexandra Nechita 
140*c9a3f8c7SRamona Alexandra Nechita struct ad7779_state {
141*c9a3f8c7SRamona Alexandra Nechita 	struct spi_device *spi;
142*c9a3f8c7SRamona Alexandra Nechita 	const struct ad7779_chip_info *chip_info;
143*c9a3f8c7SRamona Alexandra Nechita 	struct clk *mclk;
144*c9a3f8c7SRamona Alexandra Nechita 	struct iio_trigger *trig;
145*c9a3f8c7SRamona Alexandra Nechita 	struct completion completion;
146*c9a3f8c7SRamona Alexandra Nechita 	unsigned int sampling_freq;
147*c9a3f8c7SRamona Alexandra Nechita 	enum ad7779_filter filter_enabled;
148*c9a3f8c7SRamona Alexandra Nechita 	/*
149*c9a3f8c7SRamona Alexandra Nechita 	 * DMA (thus cache coherency maintenance) requires the
150*c9a3f8c7SRamona Alexandra Nechita 	 * transfer buffers to live in their own cache lines.
151*c9a3f8c7SRamona Alexandra Nechita 	 */
152*c9a3f8c7SRamona Alexandra Nechita 	struct {
153*c9a3f8c7SRamona Alexandra Nechita 		u32 chans[8];
154*c9a3f8c7SRamona Alexandra Nechita 		aligned_s64 timestamp;
155*c9a3f8c7SRamona Alexandra Nechita 	} data __aligned(IIO_DMA_MINALIGN);
156*c9a3f8c7SRamona Alexandra Nechita 	u32			spidata_tx[8];
157*c9a3f8c7SRamona Alexandra Nechita 	u8			reg_rx_buf[3];
158*c9a3f8c7SRamona Alexandra Nechita 	u8			reg_tx_buf[3];
159*c9a3f8c7SRamona Alexandra Nechita 	u8			reset_buf[8];
160*c9a3f8c7SRamona Alexandra Nechita };
161*c9a3f8c7SRamona Alexandra Nechita 
162*c9a3f8c7SRamona Alexandra Nechita static const char * const ad7779_filter_type[] = {
163*c9a3f8c7SRamona Alexandra Nechita 	[AD7779_SINC3] = "sinc3",
164*c9a3f8c7SRamona Alexandra Nechita 	[AD7779_SINC5] = "sinc5",
165*c9a3f8c7SRamona Alexandra Nechita };
166*c9a3f8c7SRamona Alexandra Nechita 
167*c9a3f8c7SRamona Alexandra Nechita static const char * const ad7779_power_supplies[] = {
168*c9a3f8c7SRamona Alexandra Nechita 	"avdd1", "avdd2", "avdd4",
169*c9a3f8c7SRamona Alexandra Nechita };
170*c9a3f8c7SRamona Alexandra Nechita 
171*c9a3f8c7SRamona Alexandra Nechita static int ad7779_spi_read(struct ad7779_state *st, u8 reg, u8 *rbuf)
172*c9a3f8c7SRamona Alexandra Nechita {
173*c9a3f8c7SRamona Alexandra Nechita 	int ret;
174*c9a3f8c7SRamona Alexandra Nechita 	u8 crc_buf[2];
175*c9a3f8c7SRamona Alexandra Nechita 	u8 exp_crc;
176*c9a3f8c7SRamona Alexandra Nechita 	struct spi_transfer t = {
177*c9a3f8c7SRamona Alexandra Nechita 		.tx_buf = st->reg_tx_buf,
178*c9a3f8c7SRamona Alexandra Nechita 		.rx_buf = st->reg_rx_buf,
179*c9a3f8c7SRamona Alexandra Nechita 	};
180*c9a3f8c7SRamona Alexandra Nechita 
181*c9a3f8c7SRamona Alexandra Nechita 	st->reg_tx_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
182*c9a3f8c7SRamona Alexandra Nechita 	st->reg_tx_buf[1] = 0;
183*c9a3f8c7SRamona Alexandra Nechita 
184*c9a3f8c7SRamona Alexandra Nechita 	if (reg == AD7779_REG_GEN_ERR_REG_1_EN) {
185*c9a3f8c7SRamona Alexandra Nechita 		t.len = 2;
186*c9a3f8c7SRamona Alexandra Nechita 	} else {
187*c9a3f8c7SRamona Alexandra Nechita 		t.len = 3;
188*c9a3f8c7SRamona Alexandra Nechita 		st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
189*c9a3f8c7SRamona Alexandra Nechita 					 t.len - 1, 0);
190*c9a3f8c7SRamona Alexandra Nechita 	}
191*c9a3f8c7SRamona Alexandra Nechita 
192*c9a3f8c7SRamona Alexandra Nechita 	ret = spi_sync_transfer(st->spi, &t, 1);
193*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
194*c9a3f8c7SRamona Alexandra Nechita 		return ret;
195*c9a3f8c7SRamona Alexandra Nechita 
196*c9a3f8c7SRamona Alexandra Nechita 	crc_buf[0] = AD7779_SPI_READ_CMD | FIELD_GET(AD7779_REG_MSK, reg);
197*c9a3f8c7SRamona Alexandra Nechita 	crc_buf[1] = st->reg_rx_buf[1];
198*c9a3f8c7SRamona Alexandra Nechita 	exp_crc = crc8(ad7779_crc8_table, crc_buf, ARRAY_SIZE(crc_buf), 0);
199*c9a3f8c7SRamona Alexandra Nechita 	if (reg != AD7779_REG_GEN_ERR_REG_1_EN && exp_crc != st->reg_rx_buf[2]) {
200*c9a3f8c7SRamona Alexandra Nechita 		dev_err(&st->spi->dev, "Bad CRC %x, expected %x",
201*c9a3f8c7SRamona Alexandra Nechita 			st->reg_rx_buf[2], exp_crc);
202*c9a3f8c7SRamona Alexandra Nechita 		return -EINVAL;
203*c9a3f8c7SRamona Alexandra Nechita 	}
204*c9a3f8c7SRamona Alexandra Nechita 	*rbuf = st->reg_rx_buf[1];
205*c9a3f8c7SRamona Alexandra Nechita 
206*c9a3f8c7SRamona Alexandra Nechita 	return 0;
207*c9a3f8c7SRamona Alexandra Nechita }
208*c9a3f8c7SRamona Alexandra Nechita 
209*c9a3f8c7SRamona Alexandra Nechita static int ad7779_spi_write(struct ad7779_state *st, u8 reg, u8 val)
210*c9a3f8c7SRamona Alexandra Nechita {
211*c9a3f8c7SRamona Alexandra Nechita 	u8 length = 3;
212*c9a3f8c7SRamona Alexandra Nechita 
213*c9a3f8c7SRamona Alexandra Nechita 	st->reg_tx_buf[0] = FIELD_GET(AD7779_REG_MSK, reg);
214*c9a3f8c7SRamona Alexandra Nechita 	st->reg_tx_buf[1] = val;
215*c9a3f8c7SRamona Alexandra Nechita 	if (reg == AD7779_REG_GEN_ERR_REG_1_EN)
216*c9a3f8c7SRamona Alexandra Nechita 		length = 2;
217*c9a3f8c7SRamona Alexandra Nechita 	else
218*c9a3f8c7SRamona Alexandra Nechita 		st->reg_tx_buf[2] = crc8(ad7779_crc8_table, st->reg_tx_buf,
219*c9a3f8c7SRamona Alexandra Nechita 					 length - 1, 0);
220*c9a3f8c7SRamona Alexandra Nechita 
221*c9a3f8c7SRamona Alexandra Nechita 	return spi_write(st->spi, st->reg_tx_buf, length);
222*c9a3f8c7SRamona Alexandra Nechita }
223*c9a3f8c7SRamona Alexandra Nechita 
224*c9a3f8c7SRamona Alexandra Nechita static int ad7779_spi_write_mask(struct ad7779_state *st, u8 reg, u8 mask,
225*c9a3f8c7SRamona Alexandra Nechita 				 u8 val)
226*c9a3f8c7SRamona Alexandra Nechita {
227*c9a3f8c7SRamona Alexandra Nechita 	int ret;
228*c9a3f8c7SRamona Alexandra Nechita 	u8 regval, data;
229*c9a3f8c7SRamona Alexandra Nechita 
230*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, reg, &data);
231*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
232*c9a3f8c7SRamona Alexandra Nechita 		return ret;
233*c9a3f8c7SRamona Alexandra Nechita 
234*c9a3f8c7SRamona Alexandra Nechita 	regval = (data & ~mask) | (val & mask);
235*c9a3f8c7SRamona Alexandra Nechita 
236*c9a3f8c7SRamona Alexandra Nechita 	if (regval == data)
237*c9a3f8c7SRamona Alexandra Nechita 		return 0;
238*c9a3f8c7SRamona Alexandra Nechita 
239*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write(st, reg, regval);
240*c9a3f8c7SRamona Alexandra Nechita }
241*c9a3f8c7SRamona Alexandra Nechita 
242*c9a3f8c7SRamona Alexandra Nechita static int ad7779_reg_access(struct iio_dev *indio_dev,
243*c9a3f8c7SRamona Alexandra Nechita 			     unsigned int reg,
244*c9a3f8c7SRamona Alexandra Nechita 			     unsigned int writeval,
245*c9a3f8c7SRamona Alexandra Nechita 			     unsigned int *readval)
246*c9a3f8c7SRamona Alexandra Nechita {
247*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
248*c9a3f8c7SRamona Alexandra Nechita 	u8 rval;
249*c9a3f8c7SRamona Alexandra Nechita 	int ret;
250*c9a3f8c7SRamona Alexandra Nechita 
251*c9a3f8c7SRamona Alexandra Nechita 	if (readval) {
252*c9a3f8c7SRamona Alexandra Nechita 		ret = ad7779_spi_read(st, reg, &rval);
253*c9a3f8c7SRamona Alexandra Nechita 		*readval = rval;
254*c9a3f8c7SRamona Alexandra Nechita 		return ret;
255*c9a3f8c7SRamona Alexandra Nechita 	}
256*c9a3f8c7SRamona Alexandra Nechita 
257*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write(st, reg, writeval);
258*c9a3f8c7SRamona Alexandra Nechita }
259*c9a3f8c7SRamona Alexandra Nechita 
260*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_sampling_frequency(struct ad7779_state *st,
261*c9a3f8c7SRamona Alexandra Nechita 					 unsigned int sampling_freq)
262*c9a3f8c7SRamona Alexandra Nechita {
263*c9a3f8c7SRamona Alexandra Nechita 	int ret;
264*c9a3f8c7SRamona Alexandra Nechita 	unsigned int dec;
265*c9a3f8c7SRamona Alexandra Nechita 	unsigned int frac;
266*c9a3f8c7SRamona Alexandra Nechita 	unsigned int div;
267*c9a3f8c7SRamona Alexandra Nechita 	unsigned int decimal;
268*c9a3f8c7SRamona Alexandra Nechita 	unsigned int freq_khz;
269*c9a3f8c7SRamona Alexandra Nechita 
270*c9a3f8c7SRamona Alexandra Nechita 	if (st->filter_enabled == AD7779_SINC3 &&
271*c9a3f8c7SRamona Alexandra Nechita 	    sampling_freq > AD7779_SINC3_MAXFREQ)
272*c9a3f8c7SRamona Alexandra Nechita 		return -EINVAL;
273*c9a3f8c7SRamona Alexandra Nechita 
274*c9a3f8c7SRamona Alexandra Nechita 	if (st->filter_enabled == AD7779_SINC5 &&
275*c9a3f8c7SRamona Alexandra Nechita 	    sampling_freq > AD7779_SINC5_MAXFREQ)
276*c9a3f8c7SRamona Alexandra Nechita 		return -EINVAL;
277*c9a3f8c7SRamona Alexandra Nechita 
278*c9a3f8c7SRamona Alexandra Nechita 	if (sampling_freq > AD7779_SPIMODE_MAX_SAMP_FREQ)
279*c9a3f8c7SRamona Alexandra Nechita 		return -EINVAL;
280*c9a3f8c7SRamona Alexandra Nechita 
281*c9a3f8c7SRamona Alexandra Nechita 	div = AD7779_HIGHPOWER_DIV;
282*c9a3f8c7SRamona Alexandra Nechita 
283*c9a3f8c7SRamona Alexandra Nechita 	freq_khz = sampling_freq / HZ_PER_KHZ;
284*c9a3f8c7SRamona Alexandra Nechita 	dec = div / freq_khz;
285*c9a3f8c7SRamona Alexandra Nechita 	frac = div % freq_khz;
286*c9a3f8c7SRamona Alexandra Nechita 
287*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
288*c9a3f8c7SRamona Alexandra Nechita 			       FIELD_GET(AD7779_FREQ_MSB_MSK, dec));
289*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
290*c9a3f8c7SRamona Alexandra Nechita 		return ret;
291*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
292*c9a3f8c7SRamona Alexandra Nechita 			       FIELD_GET(AD7779_FREQ_LSB_MSK, dec));
293*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
294*c9a3f8c7SRamona Alexandra Nechita 		return ret;
295*c9a3f8c7SRamona Alexandra Nechita 
296*c9a3f8c7SRamona Alexandra Nechita 	if (frac) {
297*c9a3f8c7SRamona Alexandra Nechita 		/*
298*c9a3f8c7SRamona Alexandra Nechita 		 * In order to obtain the first three decimals of the decimation
299*c9a3f8c7SRamona Alexandra Nechita 		 * the initial number is multiplied with 10^3 prior to the
300*c9a3f8c7SRamona Alexandra Nechita 		 * division, then the original division result is subtracted and
301*c9a3f8c7SRamona Alexandra Nechita 		 * the number is divided by 10^3.
302*c9a3f8c7SRamona Alexandra Nechita 		 */
303*c9a3f8c7SRamona Alexandra Nechita 		decimal = ((mult_frac(div, KILO, freq_khz) - dec * KILO) << 16)
304*c9a3f8c7SRamona Alexandra Nechita 			  / KILO;
305*c9a3f8c7SRamona Alexandra Nechita 		ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
306*c9a3f8c7SRamona Alexandra Nechita 				       FIELD_GET(AD7779_FREQ_MSB_MSK, decimal));
307*c9a3f8c7SRamona Alexandra Nechita 		if (ret)
308*c9a3f8c7SRamona Alexandra Nechita 			return ret;
309*c9a3f8c7SRamona Alexandra Nechita 		ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
310*c9a3f8c7SRamona Alexandra Nechita 				       FIELD_GET(AD7779_FREQ_LSB_MSK, decimal));
311*c9a3f8c7SRamona Alexandra Nechita 		if (ret)
312*c9a3f8c7SRamona Alexandra Nechita 			return ret;
313*c9a3f8c7SRamona Alexandra Nechita 	} else {
314*c9a3f8c7SRamona Alexandra Nechita 		ret = ad7779_spi_write(st, AD7779_REG_SRC_N_MSB,
315*c9a3f8c7SRamona Alexandra Nechita 				       FIELD_GET(AD7779_FREQ_MSB_MSK, 0x0));
316*c9a3f8c7SRamona Alexandra Nechita 		if (ret)
317*c9a3f8c7SRamona Alexandra Nechita 			return ret;
318*c9a3f8c7SRamona Alexandra Nechita 		ret = ad7779_spi_write(st, AD7779_REG_SRC_N_LSB,
319*c9a3f8c7SRamona Alexandra Nechita 				       FIELD_GET(AD7779_FREQ_LSB_MSK, 0x0));
320*c9a3f8c7SRamona Alexandra Nechita 		if (ret)
321*c9a3f8c7SRamona Alexandra Nechita 			return ret;
322*c9a3f8c7SRamona Alexandra Nechita 	}
323*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, BIT(0));
324*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
325*c9a3f8c7SRamona Alexandra Nechita 		return ret;
326*c9a3f8c7SRamona Alexandra Nechita 
327*c9a3f8c7SRamona Alexandra Nechita 	/* SRC update settling time */
328*c9a3f8c7SRamona Alexandra Nechita 	fsleep(15);
329*c9a3f8c7SRamona Alexandra Nechita 
330*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_SRC_UPDATE, 0x0);
331*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
332*c9a3f8c7SRamona Alexandra Nechita 		return ret;
333*c9a3f8c7SRamona Alexandra Nechita 
334*c9a3f8c7SRamona Alexandra Nechita 	/* SRC update settling time */
335*c9a3f8c7SRamona Alexandra Nechita 	fsleep(15);
336*c9a3f8c7SRamona Alexandra Nechita 
337*c9a3f8c7SRamona Alexandra Nechita 	st->sampling_freq = sampling_freq;
338*c9a3f8c7SRamona Alexandra Nechita 
339*c9a3f8c7SRamona Alexandra Nechita 	return 0;
340*c9a3f8c7SRamona Alexandra Nechita }
341*c9a3f8c7SRamona Alexandra Nechita 
342*c9a3f8c7SRamona Alexandra Nechita static int ad7779_get_filter(struct iio_dev *indio_dev,
343*c9a3f8c7SRamona Alexandra Nechita 			     struct iio_chan_spec const *chan)
344*c9a3f8c7SRamona Alexandra Nechita {
345*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
346*c9a3f8c7SRamona Alexandra Nechita 	u8 temp;
347*c9a3f8c7SRamona Alexandra Nechita 	int ret;
348*c9a3f8c7SRamona Alexandra Nechita 
349*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_GENERAL_USER_CONFIG_2, &temp);
350*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
351*c9a3f8c7SRamona Alexandra Nechita 		return ret;
352*c9a3f8c7SRamona Alexandra Nechita 
353*c9a3f8c7SRamona Alexandra Nechita 	return FIELD_GET(AD7779_FILTER_MSK, temp);
354*c9a3f8c7SRamona Alexandra Nechita }
355*c9a3f8c7SRamona Alexandra Nechita 
356*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_filter(struct iio_dev *indio_dev,
357*c9a3f8c7SRamona Alexandra Nechita 			     struct iio_chan_spec const *chan,
358*c9a3f8c7SRamona Alexandra Nechita 			     unsigned int mode)
359*c9a3f8c7SRamona Alexandra Nechita {
360*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
361*c9a3f8c7SRamona Alexandra Nechita 	int ret;
362*c9a3f8c7SRamona Alexandra Nechita 
363*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st,
364*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_REG_GENERAL_USER_CONFIG_2,
365*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_FILTER_MSK,
366*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_FILTER_MSK, mode));
367*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
368*c9a3f8c7SRamona Alexandra Nechita 		return ret;
369*c9a3f8c7SRamona Alexandra Nechita 
370*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_set_sampling_frequency(st, st->sampling_freq);
371*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
372*c9a3f8c7SRamona Alexandra Nechita 		return ret;
373*c9a3f8c7SRamona Alexandra Nechita 
374*c9a3f8c7SRamona Alexandra Nechita 	st->filter_enabled = mode;
375*c9a3f8c7SRamona Alexandra Nechita 
376*c9a3f8c7SRamona Alexandra Nechita 	return 0;
377*c9a3f8c7SRamona Alexandra Nechita }
378*c9a3f8c7SRamona Alexandra Nechita 
379*c9a3f8c7SRamona Alexandra Nechita static int ad7779_get_calibscale(struct ad7779_state *st, int channel)
380*c9a3f8c7SRamona Alexandra Nechita {
381*c9a3f8c7SRamona Alexandra Nechita 	int ret;
382*c9a3f8c7SRamona Alexandra Nechita 	u8 calibscale[3];
383*c9a3f8c7SRamona Alexandra Nechita 
384*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
385*c9a3f8c7SRamona Alexandra Nechita 			      &calibscale[0]);
386*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
387*c9a3f8c7SRamona Alexandra Nechita 		return ret;
388*c9a3f8c7SRamona Alexandra Nechita 
389*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
390*c9a3f8c7SRamona Alexandra Nechita 			      &calibscale[1]);
391*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
392*c9a3f8c7SRamona Alexandra Nechita 		return ret;
393*c9a3f8c7SRamona Alexandra Nechita 
394*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
395*c9a3f8c7SRamona Alexandra Nechita 			      &calibscale[2]);
396*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
397*c9a3f8c7SRamona Alexandra Nechita 		return ret;
398*c9a3f8c7SRamona Alexandra Nechita 
399*c9a3f8c7SRamona Alexandra Nechita 	return get_unaligned_be24(calibscale);
400*c9a3f8c7SRamona Alexandra Nechita }
401*c9a3f8c7SRamona Alexandra Nechita 
402*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_calibscale(struct ad7779_state *st, int channel, int val)
403*c9a3f8c7SRamona Alexandra Nechita {
404*c9a3f8c7SRamona Alexandra Nechita 	int ret;
405*c9a3f8c7SRamona Alexandra Nechita 	unsigned int gain;
406*c9a3f8c7SRamona Alexandra Nechita 	u8 gain_bytes[3];
407*c9a3f8c7SRamona Alexandra Nechita 
408*c9a3f8c7SRamona Alexandra Nechita 	/*
409*c9a3f8c7SRamona Alexandra Nechita 	 * The gain value is relative to 0x555555, which represents a gain of 1
410*c9a3f8c7SRamona Alexandra Nechita 	 */
411*c9a3f8c7SRamona Alexandra Nechita 	gain = DIV_ROUND_CLOSEST_ULL((u64)val * 5592405LL, MEGA);
412*c9a3f8c7SRamona Alexandra Nechita 	put_unaligned_be24(gain, gain_bytes);
413*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_UPPER_BYTE(channel),
414*c9a3f8c7SRamona Alexandra Nechita 			       gain_bytes[0]);
415*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
416*c9a3f8c7SRamona Alexandra Nechita 		return ret;
417*c9a3f8c7SRamona Alexandra Nechita 
418*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_CH_GAIN_MID_BYTE(channel),
419*c9a3f8c7SRamona Alexandra Nechita 			       gain_bytes[1]);
420*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
421*c9a3f8c7SRamona Alexandra Nechita 		return ret;
422*c9a3f8c7SRamona Alexandra Nechita 
423*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write(st, AD7779_REG_CH_GAIN_LOWER_BYTE(channel),
424*c9a3f8c7SRamona Alexandra Nechita 				gain_bytes[2]);
425*c9a3f8c7SRamona Alexandra Nechita }
426*c9a3f8c7SRamona Alexandra Nechita 
427*c9a3f8c7SRamona Alexandra Nechita static int ad7779_get_calibbias(struct ad7779_state *st, int channel)
428*c9a3f8c7SRamona Alexandra Nechita {
429*c9a3f8c7SRamona Alexandra Nechita 	int ret;
430*c9a3f8c7SRamona Alexandra Nechita 	u8 calibbias[3];
431*c9a3f8c7SRamona Alexandra Nechita 
432*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
433*c9a3f8c7SRamona Alexandra Nechita 			      &calibbias[0]);
434*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
435*c9a3f8c7SRamona Alexandra Nechita 		return ret;
436*c9a3f8c7SRamona Alexandra Nechita 
437*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
438*c9a3f8c7SRamona Alexandra Nechita 			      &calibbias[1]);
439*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
440*c9a3f8c7SRamona Alexandra Nechita 		return ret;
441*c9a3f8c7SRamona Alexandra Nechita 
442*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_read(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
443*c9a3f8c7SRamona Alexandra Nechita 			      &calibbias[2]);
444*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
445*c9a3f8c7SRamona Alexandra Nechita 		return ret;
446*c9a3f8c7SRamona Alexandra Nechita 
447*c9a3f8c7SRamona Alexandra Nechita 	return get_unaligned_be24(calibbias);
448*c9a3f8c7SRamona Alexandra Nechita }
449*c9a3f8c7SRamona Alexandra Nechita 
450*c9a3f8c7SRamona Alexandra Nechita static int ad7779_set_calibbias(struct ad7779_state *st, int channel, int val)
451*c9a3f8c7SRamona Alexandra Nechita {
452*c9a3f8c7SRamona Alexandra Nechita 	int ret;
453*c9a3f8c7SRamona Alexandra Nechita 	u8 calibbias[3];
454*c9a3f8c7SRamona Alexandra Nechita 
455*c9a3f8c7SRamona Alexandra Nechita 	put_unaligned_be24(val, calibbias);
456*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_UPPER_BYTE(channel),
457*c9a3f8c7SRamona Alexandra Nechita 			       calibbias[0]);
458*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
459*c9a3f8c7SRamona Alexandra Nechita 		return ret;
460*c9a3f8c7SRamona Alexandra Nechita 
461*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write(st, AD7779_REG_CH_OFFSET_MID_BYTE(channel),
462*c9a3f8c7SRamona Alexandra Nechita 			       calibbias[1]);
463*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
464*c9a3f8c7SRamona Alexandra Nechita 		return ret;
465*c9a3f8c7SRamona Alexandra Nechita 
466*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write(st, AD7779_REG_CH_OFFSET_LOWER_BYTE(channel),
467*c9a3f8c7SRamona Alexandra Nechita 				calibbias[2]);
468*c9a3f8c7SRamona Alexandra Nechita }
469*c9a3f8c7SRamona Alexandra Nechita 
470*c9a3f8c7SRamona Alexandra Nechita static int ad7779_read_raw(struct iio_dev *indio_dev,
471*c9a3f8c7SRamona Alexandra Nechita 			   struct iio_chan_spec const *chan, int *val,
472*c9a3f8c7SRamona Alexandra Nechita 			   int *val2, long mask)
473*c9a3f8c7SRamona Alexandra Nechita {
474*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
475*c9a3f8c7SRamona Alexandra Nechita 	int ret;
476*c9a3f8c7SRamona Alexandra Nechita 
477*c9a3f8c7SRamona Alexandra Nechita 	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
478*c9a3f8c7SRamona Alexandra Nechita 		switch (mask) {
479*c9a3f8c7SRamona Alexandra Nechita 		case IIO_CHAN_INFO_CALIBSCALE:
480*c9a3f8c7SRamona Alexandra Nechita 			ret = ad7779_get_calibscale(st, chan->channel);
481*c9a3f8c7SRamona Alexandra Nechita 			if (ret < 0)
482*c9a3f8c7SRamona Alexandra Nechita 				return ret;
483*c9a3f8c7SRamona Alexandra Nechita 			*val = ret;
484*c9a3f8c7SRamona Alexandra Nechita 			*val2 = GAIN_REL;
485*c9a3f8c7SRamona Alexandra Nechita 			return IIO_VAL_FRACTIONAL;
486*c9a3f8c7SRamona Alexandra Nechita 		case IIO_CHAN_INFO_CALIBBIAS:
487*c9a3f8c7SRamona Alexandra Nechita 			ret = ad7779_get_calibbias(st, chan->channel);
488*c9a3f8c7SRamona Alexandra Nechita 			if (ret < 0)
489*c9a3f8c7SRamona Alexandra Nechita 				return ret;
490*c9a3f8c7SRamona Alexandra Nechita 			*val = ret;
491*c9a3f8c7SRamona Alexandra Nechita 			return IIO_VAL_INT;
492*c9a3f8c7SRamona Alexandra Nechita 		case IIO_CHAN_INFO_SAMP_FREQ:
493*c9a3f8c7SRamona Alexandra Nechita 			*val = st->sampling_freq;
494*c9a3f8c7SRamona Alexandra Nechita 			if (*val < 0)
495*c9a3f8c7SRamona Alexandra Nechita 				return -EINVAL;
496*c9a3f8c7SRamona Alexandra Nechita 			return IIO_VAL_INT;
497*c9a3f8c7SRamona Alexandra Nechita 		default:
498*c9a3f8c7SRamona Alexandra Nechita 			return -EINVAL;
499*c9a3f8c7SRamona Alexandra Nechita 		}
500*c9a3f8c7SRamona Alexandra Nechita 	}
501*c9a3f8c7SRamona Alexandra Nechita 	unreachable();
502*c9a3f8c7SRamona Alexandra Nechita }
503*c9a3f8c7SRamona Alexandra Nechita 
504*c9a3f8c7SRamona Alexandra Nechita static int ad7779_write_raw(struct iio_dev *indio_dev,
505*c9a3f8c7SRamona Alexandra Nechita 			    struct iio_chan_spec const *chan, int val, int val2,
506*c9a3f8c7SRamona Alexandra Nechita 			    long mask)
507*c9a3f8c7SRamona Alexandra Nechita {
508*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
509*c9a3f8c7SRamona Alexandra Nechita 
510*c9a3f8c7SRamona Alexandra Nechita 	iio_device_claim_direct_scoped(return -EBUSY, indio_dev) {
511*c9a3f8c7SRamona Alexandra Nechita 		switch (mask) {
512*c9a3f8c7SRamona Alexandra Nechita 		case IIO_CHAN_INFO_CALIBSCALE:
513*c9a3f8c7SRamona Alexandra Nechita 			return ad7779_set_calibscale(st, chan->channel, val2);
514*c9a3f8c7SRamona Alexandra Nechita 		case IIO_CHAN_INFO_CALIBBIAS:
515*c9a3f8c7SRamona Alexandra Nechita 			return ad7779_set_calibbias(st, chan->channel, val);
516*c9a3f8c7SRamona Alexandra Nechita 		case IIO_CHAN_INFO_SAMP_FREQ:
517*c9a3f8c7SRamona Alexandra Nechita 			return ad7779_set_sampling_frequency(st, val);
518*c9a3f8c7SRamona Alexandra Nechita 		default:
519*c9a3f8c7SRamona Alexandra Nechita 			return -EINVAL;
520*c9a3f8c7SRamona Alexandra Nechita 		}
521*c9a3f8c7SRamona Alexandra Nechita 	}
522*c9a3f8c7SRamona Alexandra Nechita 	unreachable();
523*c9a3f8c7SRamona Alexandra Nechita }
524*c9a3f8c7SRamona Alexandra Nechita 
525*c9a3f8c7SRamona Alexandra Nechita static int ad7779_buffer_preenable(struct iio_dev *indio_dev)
526*c9a3f8c7SRamona Alexandra Nechita {
527*c9a3f8c7SRamona Alexandra Nechita 	int ret;
528*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
529*c9a3f8c7SRamona Alexandra Nechita 
530*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st,
531*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_REG_GENERAL_USER_CONFIG_3,
532*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_MOD_SPI_EN_MSK,
533*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_MOD_SPI_EN_MSK, 1));
534*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
535*c9a3f8c7SRamona Alexandra Nechita 		return ret;
536*c9a3f8c7SRamona Alexandra Nechita 
537*c9a3f8c7SRamona Alexandra Nechita 	/*
538*c9a3f8c7SRamona Alexandra Nechita 	 * DRDY output cannot be disabled at device level therefore we mask
539*c9a3f8c7SRamona Alexandra Nechita 	 * the irq at host end.
540*c9a3f8c7SRamona Alexandra Nechita 	 */
541*c9a3f8c7SRamona Alexandra Nechita 	enable_irq(st->spi->irq);
542*c9a3f8c7SRamona Alexandra Nechita 
543*c9a3f8c7SRamona Alexandra Nechita 	return 0;
544*c9a3f8c7SRamona Alexandra Nechita }
545*c9a3f8c7SRamona Alexandra Nechita 
546*c9a3f8c7SRamona Alexandra Nechita static int ad7779_buffer_postdisable(struct iio_dev *indio_dev)
547*c9a3f8c7SRamona Alexandra Nechita {
548*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
549*c9a3f8c7SRamona Alexandra Nechita 
550*c9a3f8c7SRamona Alexandra Nechita 	disable_irq(st->spi->irq);
551*c9a3f8c7SRamona Alexandra Nechita 
552*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write(st, AD7779_REG_GENERAL_USER_CONFIG_3,
553*c9a3f8c7SRamona Alexandra Nechita 			       AD7779_DISABLE_SD);
554*c9a3f8c7SRamona Alexandra Nechita }
555*c9a3f8c7SRamona Alexandra Nechita 
556*c9a3f8c7SRamona Alexandra Nechita static irqreturn_t ad7779_trigger_handler(int irq, void *p)
557*c9a3f8c7SRamona Alexandra Nechita {
558*c9a3f8c7SRamona Alexandra Nechita 	struct iio_poll_func *pf = p;
559*c9a3f8c7SRamona Alexandra Nechita 	struct iio_dev *indio_dev = pf->indio_dev;
560*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
561*c9a3f8c7SRamona Alexandra Nechita 	int ret;
562*c9a3f8c7SRamona Alexandra Nechita 	struct spi_transfer t = {
563*c9a3f8c7SRamona Alexandra Nechita 		.rx_buf = st->data.chans,
564*c9a3f8c7SRamona Alexandra Nechita 		.tx_buf = st->spidata_tx,
565*c9a3f8c7SRamona Alexandra Nechita 		.len = AD7779_NUM_CHANNELS * AD7779_CHAN_DATA_SIZE,
566*c9a3f8c7SRamona Alexandra Nechita 	};
567*c9a3f8c7SRamona Alexandra Nechita 
568*c9a3f8c7SRamona Alexandra Nechita 	st->spidata_tx[0] = AD7779_SPI_READ_CMD;
569*c9a3f8c7SRamona Alexandra Nechita 	ret = spi_sync_transfer(st->spi, &t, 1);
570*c9a3f8c7SRamona Alexandra Nechita 	if (ret) {
571*c9a3f8c7SRamona Alexandra Nechita 		dev_err(&st->spi->dev, "SPI transfer error in IRQ handler");
572*c9a3f8c7SRamona Alexandra Nechita 		goto exit_handler;
573*c9a3f8c7SRamona Alexandra Nechita 	}
574*c9a3f8c7SRamona Alexandra Nechita 
575*c9a3f8c7SRamona Alexandra Nechita 	iio_push_to_buffers_with_timestamp(indio_dev, &st->data, pf->timestamp);
576*c9a3f8c7SRamona Alexandra Nechita 
577*c9a3f8c7SRamona Alexandra Nechita exit_handler:
578*c9a3f8c7SRamona Alexandra Nechita 	iio_trigger_notify_done(indio_dev->trig);
579*c9a3f8c7SRamona Alexandra Nechita 	return IRQ_HANDLED;
580*c9a3f8c7SRamona Alexandra Nechita }
581*c9a3f8c7SRamona Alexandra Nechita 
582*c9a3f8c7SRamona Alexandra Nechita static int ad7779_reset(struct iio_dev *indio_dev, struct gpio_desc *reset_gpio)
583*c9a3f8c7SRamona Alexandra Nechita {
584*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
585*c9a3f8c7SRamona Alexandra Nechita 	int ret;
586*c9a3f8c7SRamona Alexandra Nechita 	struct spi_transfer t = {
587*c9a3f8c7SRamona Alexandra Nechita 		.tx_buf = st->reset_buf,
588*c9a3f8c7SRamona Alexandra Nechita 		.len = 8,
589*c9a3f8c7SRamona Alexandra Nechita 	};
590*c9a3f8c7SRamona Alexandra Nechita 
591*c9a3f8c7SRamona Alexandra Nechita 	if (reset_gpio) {
592*c9a3f8c7SRamona Alexandra Nechita 		gpiod_set_value(reset_gpio, 1);
593*c9a3f8c7SRamona Alexandra Nechita 		/* Delay for reset to occur is 225 microseconds */
594*c9a3f8c7SRamona Alexandra Nechita 		fsleep(230);
595*c9a3f8c7SRamona Alexandra Nechita 		ret = 0;
596*c9a3f8c7SRamona Alexandra Nechita 	} else {
597*c9a3f8c7SRamona Alexandra Nechita 		memset(st->reset_buf, 0xff, sizeof(st->reset_buf));
598*c9a3f8c7SRamona Alexandra Nechita 		ret = spi_sync_transfer(st->spi, &t, 1);
599*c9a3f8c7SRamona Alexandra Nechita 		if (ret)
600*c9a3f8c7SRamona Alexandra Nechita 			return ret;
601*c9a3f8c7SRamona Alexandra Nechita 	}
602*c9a3f8c7SRamona Alexandra Nechita 
603*c9a3f8c7SRamona Alexandra Nechita 	/* Delay for reset to occur is 225 microseconds */
604*c9a3f8c7SRamona Alexandra Nechita 	fsleep(230);
605*c9a3f8c7SRamona Alexandra Nechita 
606*c9a3f8c7SRamona Alexandra Nechita 	return ret;
607*c9a3f8c7SRamona Alexandra Nechita }
608*c9a3f8c7SRamona Alexandra Nechita 
609*c9a3f8c7SRamona Alexandra Nechita static const struct iio_info ad7779_info = {
610*c9a3f8c7SRamona Alexandra Nechita 	.read_raw = ad7779_read_raw,
611*c9a3f8c7SRamona Alexandra Nechita 	.write_raw = ad7779_write_raw,
612*c9a3f8c7SRamona Alexandra Nechita 	.debugfs_reg_access = &ad7779_reg_access,
613*c9a3f8c7SRamona Alexandra Nechita };
614*c9a3f8c7SRamona Alexandra Nechita 
615*c9a3f8c7SRamona Alexandra Nechita static const struct iio_enum ad7779_filter_enum = {
616*c9a3f8c7SRamona Alexandra Nechita 	.items = ad7779_filter_type,
617*c9a3f8c7SRamona Alexandra Nechita 	.num_items = ARRAY_SIZE(ad7779_filter_type),
618*c9a3f8c7SRamona Alexandra Nechita 	.get = ad7779_get_filter,
619*c9a3f8c7SRamona Alexandra Nechita 	.set = ad7779_set_filter,
620*c9a3f8c7SRamona Alexandra Nechita };
621*c9a3f8c7SRamona Alexandra Nechita 
622*c9a3f8c7SRamona Alexandra Nechita static const struct iio_chan_spec_ext_info ad7779_ext_filter[] = {
623*c9a3f8c7SRamona Alexandra Nechita 	IIO_ENUM("filter_type", IIO_SHARED_BY_ALL, &ad7779_filter_enum),
624*c9a3f8c7SRamona Alexandra Nechita 	IIO_ENUM_AVAILABLE("filter_type", IIO_SHARED_BY_ALL,
625*c9a3f8c7SRamona Alexandra Nechita 				  &ad7779_filter_enum),
626*c9a3f8c7SRamona Alexandra Nechita 	{ }
627*c9a3f8c7SRamona Alexandra Nechita };
628*c9a3f8c7SRamona Alexandra Nechita 
629*c9a3f8c7SRamona Alexandra Nechita #define AD777x_CHAN_S(index, _ext_info)					\
630*c9a3f8c7SRamona Alexandra Nechita 	{								\
631*c9a3f8c7SRamona Alexandra Nechita 		.type = IIO_VOLTAGE,					\
632*c9a3f8c7SRamona Alexandra Nechita 		.info_mask_separate = BIT(IIO_CHAN_INFO_CALIBSCALE)  |	\
633*c9a3f8c7SRamona Alexandra Nechita 				      BIT(IIO_CHAN_INFO_CALIBBIAS),	\
634*c9a3f8c7SRamona Alexandra Nechita 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),\
635*c9a3f8c7SRamona Alexandra Nechita 		.address = (index),					\
636*c9a3f8c7SRamona Alexandra Nechita 		.indexed = 1,						\
637*c9a3f8c7SRamona Alexandra Nechita 		.channel = (index),					\
638*c9a3f8c7SRamona Alexandra Nechita 		.scan_index = (index),					\
639*c9a3f8c7SRamona Alexandra Nechita 		.ext_info = (_ext_info),				\
640*c9a3f8c7SRamona Alexandra Nechita 		.scan_type = {						\
641*c9a3f8c7SRamona Alexandra Nechita 			.sign = 's',					\
642*c9a3f8c7SRamona Alexandra Nechita 			.realbits = 24,					\
643*c9a3f8c7SRamona Alexandra Nechita 			.storagebits = 32,				\
644*c9a3f8c7SRamona Alexandra Nechita 			.endianness = IIO_BE,				\
645*c9a3f8c7SRamona Alexandra Nechita 		},							\
646*c9a3f8c7SRamona Alexandra Nechita 	}
647*c9a3f8c7SRamona Alexandra Nechita 
648*c9a3f8c7SRamona Alexandra Nechita #define AD777x_CHAN_NO_FILTER_S(index)					\
649*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_S(index, NULL)
650*c9a3f8c7SRamona Alexandra Nechita 
651*c9a3f8c7SRamona Alexandra Nechita #define AD777x_CHAN_FILTER_S(index)					\
652*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_S(index, ad7779_ext_filter)
653*c9a3f8c7SRamona Alexandra Nechita static const struct iio_chan_spec ad7779_channels[] = {
654*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(0),
655*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(1),
656*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(2),
657*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(3),
658*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(4),
659*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(5),
660*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(6),
661*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_NO_FILTER_S(7),
662*c9a3f8c7SRamona Alexandra Nechita 	IIO_CHAN_SOFT_TIMESTAMP(8),
663*c9a3f8c7SRamona Alexandra Nechita };
664*c9a3f8c7SRamona Alexandra Nechita 
665*c9a3f8c7SRamona Alexandra Nechita static const struct iio_chan_spec ad7779_channels_filter[] = {
666*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(0),
667*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(1),
668*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(2),
669*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(3),
670*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(4),
671*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(5),
672*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(6),
673*c9a3f8c7SRamona Alexandra Nechita 	AD777x_CHAN_FILTER_S(7),
674*c9a3f8c7SRamona Alexandra Nechita 	IIO_CHAN_SOFT_TIMESTAMP(8),
675*c9a3f8c7SRamona Alexandra Nechita };
676*c9a3f8c7SRamona Alexandra Nechita 
677*c9a3f8c7SRamona Alexandra Nechita static const struct iio_buffer_setup_ops ad7779_buffer_setup_ops = {
678*c9a3f8c7SRamona Alexandra Nechita 	.preenable = ad7779_buffer_preenable,
679*c9a3f8c7SRamona Alexandra Nechita 	.postdisable = ad7779_buffer_postdisable,
680*c9a3f8c7SRamona Alexandra Nechita };
681*c9a3f8c7SRamona Alexandra Nechita 
682*c9a3f8c7SRamona Alexandra Nechita static const struct iio_trigger_ops ad7779_trigger_ops = {
683*c9a3f8c7SRamona Alexandra Nechita 	.validate_device = iio_trigger_validate_own_device,
684*c9a3f8c7SRamona Alexandra Nechita };
685*c9a3f8c7SRamona Alexandra Nechita 
686*c9a3f8c7SRamona Alexandra Nechita static int ad7779_conf(struct ad7779_state *st, struct gpio_desc *start_gpio)
687*c9a3f8c7SRamona Alexandra Nechita {
688*c9a3f8c7SRamona Alexandra Nechita 	int ret;
689*c9a3f8c7SRamona Alexandra Nechita 
690*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st, AD7779_REG_GEN_ERR_REG_1_EN,
691*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_SPI_CRC_EN_MSK,
692*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_SPI_CRC_EN_MSK, 1));
693*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
694*c9a3f8c7SRamona Alexandra Nechita 		return ret;
695*c9a3f8c7SRamona Alexandra Nechita 
696*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
697*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_USRMOD_INIT_MSK,
698*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_USRMOD_INIT_MSK, 5));
699*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
700*c9a3f8c7SRamona Alexandra Nechita 		return ret;
701*c9a3f8c7SRamona Alexandra Nechita 
702*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
703*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_DCLK_CLK_DIV_MSK,
704*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 1));
705*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
706*c9a3f8c7SRamona Alexandra Nechita 		return ret;
707*c9a3f8c7SRamona Alexandra Nechita 
708*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st, AD7779_REG_ADC_MUX_CONFIG,
709*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_REFMUX_CTRL_MSK,
710*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_REFMUX_CTRL_MSK, 1));
711*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
712*c9a3f8c7SRamona Alexandra Nechita 		return ret;
713*c9a3f8c7SRamona Alexandra Nechita 
714*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_set_sampling_frequency(st, AD7779_DEFAULT_SAMPLING_FREQ);
715*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
716*c9a3f8c7SRamona Alexandra Nechita 		return ret;
717*c9a3f8c7SRamona Alexandra Nechita 
718*c9a3f8c7SRamona Alexandra Nechita 	gpiod_set_value(start_gpio, 0);
719*c9a3f8c7SRamona Alexandra Nechita 	/* Start setup time */
720*c9a3f8c7SRamona Alexandra Nechita 	fsleep(15);
721*c9a3f8c7SRamona Alexandra Nechita 	gpiod_set_value(start_gpio, 1);
722*c9a3f8c7SRamona Alexandra Nechita 	/* Start setup time */
723*c9a3f8c7SRamona Alexandra Nechita 	fsleep(15);
724*c9a3f8c7SRamona Alexandra Nechita 	gpiod_set_value(start_gpio, 0);
725*c9a3f8c7SRamona Alexandra Nechita 	/* Start setup time */
726*c9a3f8c7SRamona Alexandra Nechita 	fsleep(15);
727*c9a3f8c7SRamona Alexandra Nechita 
728*c9a3f8c7SRamona Alexandra Nechita 	return 0;
729*c9a3f8c7SRamona Alexandra Nechita }
730*c9a3f8c7SRamona Alexandra Nechita 
731*c9a3f8c7SRamona Alexandra Nechita static int ad7779_probe(struct spi_device *spi)
732*c9a3f8c7SRamona Alexandra Nechita {
733*c9a3f8c7SRamona Alexandra Nechita 	struct iio_dev *indio_dev;
734*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st;
735*c9a3f8c7SRamona Alexandra Nechita 	struct gpio_desc *reset_gpio, *start_gpio;
736*c9a3f8c7SRamona Alexandra Nechita 	struct device *dev = &spi->dev;
737*c9a3f8c7SRamona Alexandra Nechita 	int ret = -EINVAL;
738*c9a3f8c7SRamona Alexandra Nechita 
739*c9a3f8c7SRamona Alexandra Nechita 	if (!spi->irq)
740*c9a3f8c7SRamona Alexandra Nechita 		return dev_err_probe(dev, ret, "DRDY irq not present\n");
741*c9a3f8c7SRamona Alexandra Nechita 
742*c9a3f8c7SRamona Alexandra Nechita 	indio_dev = devm_iio_device_alloc(dev, sizeof(*st));
743*c9a3f8c7SRamona Alexandra Nechita 	if (!indio_dev)
744*c9a3f8c7SRamona Alexandra Nechita 		return -ENOMEM;
745*c9a3f8c7SRamona Alexandra Nechita 
746*c9a3f8c7SRamona Alexandra Nechita 	st = iio_priv(indio_dev);
747*c9a3f8c7SRamona Alexandra Nechita 
748*c9a3f8c7SRamona Alexandra Nechita 	ret = devm_regulator_bulk_get_enable(dev,
749*c9a3f8c7SRamona Alexandra Nechita 					     ARRAY_SIZE(ad7779_power_supplies),
750*c9a3f8c7SRamona Alexandra Nechita 					     ad7779_power_supplies);
751*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
752*c9a3f8c7SRamona Alexandra Nechita 		return dev_err_probe(dev, ret,
753*c9a3f8c7SRamona Alexandra Nechita 				     "failed to get and enable supplies\n");
754*c9a3f8c7SRamona Alexandra Nechita 
755*c9a3f8c7SRamona Alexandra Nechita 	st->mclk = devm_clk_get_enabled(dev, "mclk");
756*c9a3f8c7SRamona Alexandra Nechita 	if (IS_ERR(st->mclk))
757*c9a3f8c7SRamona Alexandra Nechita 		return PTR_ERR(st->mclk);
758*c9a3f8c7SRamona Alexandra Nechita 
759*c9a3f8c7SRamona Alexandra Nechita 	reset_gpio = devm_gpiod_get_optional(dev, "reset", GPIOD_OUT_LOW);
760*c9a3f8c7SRamona Alexandra Nechita 	if (IS_ERR(reset_gpio))
761*c9a3f8c7SRamona Alexandra Nechita 		return PTR_ERR(reset_gpio);
762*c9a3f8c7SRamona Alexandra Nechita 
763*c9a3f8c7SRamona Alexandra Nechita 	start_gpio = devm_gpiod_get(dev, "start", GPIOD_OUT_HIGH);
764*c9a3f8c7SRamona Alexandra Nechita 	if (IS_ERR(start_gpio))
765*c9a3f8c7SRamona Alexandra Nechita 		return PTR_ERR(start_gpio);
766*c9a3f8c7SRamona Alexandra Nechita 
767*c9a3f8c7SRamona Alexandra Nechita 	crc8_populate_msb(ad7779_crc8_table, AD7779_CRC8_POLY);
768*c9a3f8c7SRamona Alexandra Nechita 	st->spi = spi;
769*c9a3f8c7SRamona Alexandra Nechita 
770*c9a3f8c7SRamona Alexandra Nechita 	st->chip_info = spi_get_device_match_data(spi);
771*c9a3f8c7SRamona Alexandra Nechita 	if (!st->chip_info)
772*c9a3f8c7SRamona Alexandra Nechita 		return -ENODEV;
773*c9a3f8c7SRamona Alexandra Nechita 
774*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_reset(indio_dev, reset_gpio);
775*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
776*c9a3f8c7SRamona Alexandra Nechita 		return ret;
777*c9a3f8c7SRamona Alexandra Nechita 
778*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_conf(st, start_gpio);
779*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
780*c9a3f8c7SRamona Alexandra Nechita 		return ret;
781*c9a3f8c7SRamona Alexandra Nechita 
782*c9a3f8c7SRamona Alexandra Nechita 	indio_dev->name = st->chip_info->name;
783*c9a3f8c7SRamona Alexandra Nechita 	indio_dev->info = &ad7779_info;
784*c9a3f8c7SRamona Alexandra Nechita 	indio_dev->modes = INDIO_DIRECT_MODE;
785*c9a3f8c7SRamona Alexandra Nechita 	indio_dev->channels = st->chip_info->channels;
786*c9a3f8c7SRamona Alexandra Nechita 	indio_dev->num_channels = ARRAY_SIZE(ad7779_channels);
787*c9a3f8c7SRamona Alexandra Nechita 
788*c9a3f8c7SRamona Alexandra Nechita 	st->trig = devm_iio_trigger_alloc(dev, "%s-dev%d", indio_dev->name,
789*c9a3f8c7SRamona Alexandra Nechita 					  iio_device_id(indio_dev));
790*c9a3f8c7SRamona Alexandra Nechita 	if (!st->trig)
791*c9a3f8c7SRamona Alexandra Nechita 		return -ENOMEM;
792*c9a3f8c7SRamona Alexandra Nechita 
793*c9a3f8c7SRamona Alexandra Nechita 	st->trig->ops = &ad7779_trigger_ops;
794*c9a3f8c7SRamona Alexandra Nechita 
795*c9a3f8c7SRamona Alexandra Nechita 	iio_trigger_set_drvdata(st->trig, st);
796*c9a3f8c7SRamona Alexandra Nechita 
797*c9a3f8c7SRamona Alexandra Nechita 	ret = devm_request_irq(dev, spi->irq, iio_trigger_generic_data_rdy_poll,
798*c9a3f8c7SRamona Alexandra Nechita 			       IRQF_ONESHOT | IRQF_NO_AUTOEN, indio_dev->name,
799*c9a3f8c7SRamona Alexandra Nechita 			       st->trig);
800*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
801*c9a3f8c7SRamona Alexandra Nechita 		return dev_err_probe(dev, ret, "request IRQ %d failed\n",
802*c9a3f8c7SRamona Alexandra Nechita 				     st->spi->irq);
803*c9a3f8c7SRamona Alexandra Nechita 
804*c9a3f8c7SRamona Alexandra Nechita 	ret = devm_iio_trigger_register(dev, st->trig);
805*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
806*c9a3f8c7SRamona Alexandra Nechita 		return ret;
807*c9a3f8c7SRamona Alexandra Nechita 
808*c9a3f8c7SRamona Alexandra Nechita 	indio_dev->trig = iio_trigger_get(st->trig);
809*c9a3f8c7SRamona Alexandra Nechita 
810*c9a3f8c7SRamona Alexandra Nechita 	init_completion(&st->completion);
811*c9a3f8c7SRamona Alexandra Nechita 
812*c9a3f8c7SRamona Alexandra Nechita 	ret = devm_iio_triggered_buffer_setup(dev, indio_dev,
813*c9a3f8c7SRamona Alexandra Nechita 					      &iio_pollfunc_store_time,
814*c9a3f8c7SRamona Alexandra Nechita 					      &ad7779_trigger_handler,
815*c9a3f8c7SRamona Alexandra Nechita 					      &ad7779_buffer_setup_ops);
816*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
817*c9a3f8c7SRamona Alexandra Nechita 		return ret;
818*c9a3f8c7SRamona Alexandra Nechita 
819*c9a3f8c7SRamona Alexandra Nechita 	ret = ad7779_spi_write_mask(st, AD7779_REG_DOUT_FORMAT,
820*c9a3f8c7SRamona Alexandra Nechita 				    AD7779_DCLK_CLK_DIV_MSK,
821*c9a3f8c7SRamona Alexandra Nechita 				    FIELD_PREP(AD7779_DCLK_CLK_DIV_MSK, 7));
822*c9a3f8c7SRamona Alexandra Nechita 	if (ret)
823*c9a3f8c7SRamona Alexandra Nechita 		return ret;
824*c9a3f8c7SRamona Alexandra Nechita 
825*c9a3f8c7SRamona Alexandra Nechita 	return devm_iio_device_register(dev, indio_dev);
826*c9a3f8c7SRamona Alexandra Nechita }
827*c9a3f8c7SRamona Alexandra Nechita 
828*c9a3f8c7SRamona Alexandra Nechita static int ad7779_suspend(struct device *dev)
829*c9a3f8c7SRamona Alexandra Nechita {
830*c9a3f8c7SRamona Alexandra Nechita 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
831*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
832*c9a3f8c7SRamona Alexandra Nechita 
833*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
834*c9a3f8c7SRamona Alexandra Nechita 				     AD7779_MOD_POWERMODE_MSK,
835*c9a3f8c7SRamona Alexandra Nechita 				     FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
836*c9a3f8c7SRamona Alexandra Nechita 					       AD7779_LOW_POWER));
837*c9a3f8c7SRamona Alexandra Nechita }
838*c9a3f8c7SRamona Alexandra Nechita 
839*c9a3f8c7SRamona Alexandra Nechita static int ad7779_resume(struct device *dev)
840*c9a3f8c7SRamona Alexandra Nechita {
841*c9a3f8c7SRamona Alexandra Nechita 	struct iio_dev *indio_dev = dev_get_drvdata(dev);
842*c9a3f8c7SRamona Alexandra Nechita 	struct ad7779_state *st = iio_priv(indio_dev);
843*c9a3f8c7SRamona Alexandra Nechita 
844*c9a3f8c7SRamona Alexandra Nechita 	return ad7779_spi_write_mask(st, AD7779_REG_GENERAL_USER_CONFIG_1,
845*c9a3f8c7SRamona Alexandra Nechita 				     AD7779_MOD_POWERMODE_MSK,
846*c9a3f8c7SRamona Alexandra Nechita 				     FIELD_PREP(AD7779_MOD_POWERMODE_MSK,
847*c9a3f8c7SRamona Alexandra Nechita 					       AD7779_HIGH_POWER));
848*c9a3f8c7SRamona Alexandra Nechita }
849*c9a3f8c7SRamona Alexandra Nechita 
850*c9a3f8c7SRamona Alexandra Nechita static DEFINE_SIMPLE_DEV_PM_OPS(ad7779_pm_ops, ad7779_suspend, ad7779_resume);
851*c9a3f8c7SRamona Alexandra Nechita 
852*c9a3f8c7SRamona Alexandra Nechita static const struct ad7779_chip_info ad7770_chip_info = {
853*c9a3f8c7SRamona Alexandra Nechita 	.name = "ad7770",
854*c9a3f8c7SRamona Alexandra Nechita 	.channels = ad7779_channels,
855*c9a3f8c7SRamona Alexandra Nechita };
856*c9a3f8c7SRamona Alexandra Nechita 
857*c9a3f8c7SRamona Alexandra Nechita static const struct ad7779_chip_info ad7771_chip_info = {
858*c9a3f8c7SRamona Alexandra Nechita 	.name = "ad7771",
859*c9a3f8c7SRamona Alexandra Nechita 	.channels = ad7779_channels_filter,
860*c9a3f8c7SRamona Alexandra Nechita };
861*c9a3f8c7SRamona Alexandra Nechita 
862*c9a3f8c7SRamona Alexandra Nechita static const struct ad7779_chip_info ad7779_chip_info = {
863*c9a3f8c7SRamona Alexandra Nechita 	.name = "ad7779",
864*c9a3f8c7SRamona Alexandra Nechita 	.channels = ad7779_channels,
865*c9a3f8c7SRamona Alexandra Nechita };
866*c9a3f8c7SRamona Alexandra Nechita 
867*c9a3f8c7SRamona Alexandra Nechita static const struct spi_device_id ad7779_id[] = {
868*c9a3f8c7SRamona Alexandra Nechita 	{
869*c9a3f8c7SRamona Alexandra Nechita 		.name = "ad7770",
870*c9a3f8c7SRamona Alexandra Nechita 		.driver_data = (kernel_ulong_t)&ad7770_chip_info,
871*c9a3f8c7SRamona Alexandra Nechita 	},
872*c9a3f8c7SRamona Alexandra Nechita 	{
873*c9a3f8c7SRamona Alexandra Nechita 		.name = "ad7771",
874*c9a3f8c7SRamona Alexandra Nechita 		.driver_data = (kernel_ulong_t)&ad7771_chip_info,
875*c9a3f8c7SRamona Alexandra Nechita 	},
876*c9a3f8c7SRamona Alexandra Nechita 	{
877*c9a3f8c7SRamona Alexandra Nechita 		.name = "ad7779",
878*c9a3f8c7SRamona Alexandra Nechita 		.driver_data = (kernel_ulong_t)&ad7779_chip_info,
879*c9a3f8c7SRamona Alexandra Nechita 	},
880*c9a3f8c7SRamona Alexandra Nechita 	{ }
881*c9a3f8c7SRamona Alexandra Nechita };
882*c9a3f8c7SRamona Alexandra Nechita MODULE_DEVICE_TABLE(spi, ad7779_id);
883*c9a3f8c7SRamona Alexandra Nechita 
884*c9a3f8c7SRamona Alexandra Nechita static const struct of_device_id ad7779_of_table[] = {
885*c9a3f8c7SRamona Alexandra Nechita 	{
886*c9a3f8c7SRamona Alexandra Nechita 		.compatible = "adi,ad7770",
887*c9a3f8c7SRamona Alexandra Nechita 		.data = &ad7770_chip_info,
888*c9a3f8c7SRamona Alexandra Nechita 	},
889*c9a3f8c7SRamona Alexandra Nechita 	{
890*c9a3f8c7SRamona Alexandra Nechita 		.compatible = "adi,ad7771",
891*c9a3f8c7SRamona Alexandra Nechita 		.data = &ad7771_chip_info,
892*c9a3f8c7SRamona Alexandra Nechita 	},
893*c9a3f8c7SRamona Alexandra Nechita 	{
894*c9a3f8c7SRamona Alexandra Nechita 		.compatible = "adi,ad7779",
895*c9a3f8c7SRamona Alexandra Nechita 		.data = &ad7779_chip_info,
896*c9a3f8c7SRamona Alexandra Nechita 	},
897*c9a3f8c7SRamona Alexandra Nechita 	{ }
898*c9a3f8c7SRamona Alexandra Nechita };
899*c9a3f8c7SRamona Alexandra Nechita MODULE_DEVICE_TABLE(of, ad7779_of_table);
900*c9a3f8c7SRamona Alexandra Nechita 
901*c9a3f8c7SRamona Alexandra Nechita static struct spi_driver ad7779_driver = {
902*c9a3f8c7SRamona Alexandra Nechita 	.driver = {
903*c9a3f8c7SRamona Alexandra Nechita 		.name = "ad7779",
904*c9a3f8c7SRamona Alexandra Nechita 		.pm = pm_sleep_ptr(&ad7779_pm_ops),
905*c9a3f8c7SRamona Alexandra Nechita 		.of_match_table = ad7779_of_table,
906*c9a3f8c7SRamona Alexandra Nechita 	},
907*c9a3f8c7SRamona Alexandra Nechita 	.probe = ad7779_probe,
908*c9a3f8c7SRamona Alexandra Nechita 	.id_table = ad7779_id,
909*c9a3f8c7SRamona Alexandra Nechita };
910*c9a3f8c7SRamona Alexandra Nechita module_spi_driver(ad7779_driver);
911*c9a3f8c7SRamona Alexandra Nechita 
912*c9a3f8c7SRamona Alexandra Nechita MODULE_AUTHOR("Ramona Alexandra Nechita <ramona.nechita@analog.com>");
913*c9a3f8c7SRamona Alexandra Nechita MODULE_DESCRIPTION("Analog Devices AD7779 ADC");
914*c9a3f8c7SRamona Alexandra Nechita MODULE_LICENSE("GPL");
915