xref: /openbmc/linux/drivers/iio/adc/ad7768-1.c (revision 25f7e795)
1a5f8c7daSStefan Popa // SPDX-License-Identifier: GPL-2.0
2a5f8c7daSStefan Popa /*
3a5f8c7daSStefan Popa  * Analog Devices AD7768-1 SPI ADC driver
4a5f8c7daSStefan Popa  *
5a5f8c7daSStefan Popa  * Copyright 2017 Analog Devices Inc.
6a5f8c7daSStefan Popa  */
7a5f8c7daSStefan Popa #include <linux/bitfield.h>
8a5f8c7daSStefan Popa #include <linux/clk.h>
9a5f8c7daSStefan Popa #include <linux/delay.h>
10a5f8c7daSStefan Popa #include <linux/device.h>
11a5f8c7daSStefan Popa #include <linux/err.h>
12e9517dffSStefan Popa #include <linux/gpio/consumer.h>
13a5f8c7daSStefan Popa #include <linux/kernel.h>
14a5f8c7daSStefan Popa #include <linux/module.h>
15a5f8c7daSStefan Popa #include <linux/regulator/consumer.h>
16a5f8c7daSStefan Popa #include <linux/sysfs.h>
17a5f8c7daSStefan Popa #include <linux/spi/spi.h>
18a5f8c7daSStefan Popa 
19a5f8c7daSStefan Popa #include <linux/iio/buffer.h>
20a5f8c7daSStefan Popa #include <linux/iio/iio.h>
21a5f8c7daSStefan Popa #include <linux/iio/sysfs.h>
22a5f8c7daSStefan Popa #include <linux/iio/trigger.h>
23a5f8c7daSStefan Popa #include <linux/iio/triggered_buffer.h>
24a5f8c7daSStefan Popa #include <linux/iio/trigger_consumer.h>
25a5f8c7daSStefan Popa 
26a5f8c7daSStefan Popa /* AD7768 registers definition */
27a5f8c7daSStefan Popa #define AD7768_REG_CHIP_TYPE		0x3
28a5f8c7daSStefan Popa #define AD7768_REG_PROD_ID_L		0x4
29a5f8c7daSStefan Popa #define AD7768_REG_PROD_ID_H		0x5
30a5f8c7daSStefan Popa #define AD7768_REG_CHIP_GRADE		0x6
31a5f8c7daSStefan Popa #define AD7768_REG_SCRATCH_PAD		0x0A
32a5f8c7daSStefan Popa #define AD7768_REG_VENDOR_L		0x0C
33a5f8c7daSStefan Popa #define AD7768_REG_VENDOR_H		0x0D
34a5f8c7daSStefan Popa #define AD7768_REG_INTERFACE_FORMAT	0x14
35a5f8c7daSStefan Popa #define AD7768_REG_POWER_CLOCK		0x15
36a5f8c7daSStefan Popa #define AD7768_REG_ANALOG		0x16
37a5f8c7daSStefan Popa #define AD7768_REG_ANALOG2		0x17
38a5f8c7daSStefan Popa #define AD7768_REG_CONVERSION		0x18
39a5f8c7daSStefan Popa #define AD7768_REG_DIGITAL_FILTER	0x19
40a5f8c7daSStefan Popa #define AD7768_REG_SINC3_DEC_RATE_MSB	0x1A
41a5f8c7daSStefan Popa #define AD7768_REG_SINC3_DEC_RATE_LSB	0x1B
42a5f8c7daSStefan Popa #define AD7768_REG_DUTY_CYCLE_RATIO	0x1C
43a5f8c7daSStefan Popa #define AD7768_REG_SYNC_RESET		0x1D
44a5f8c7daSStefan Popa #define AD7768_REG_GPIO_CONTROL		0x1E
45a5f8c7daSStefan Popa #define AD7768_REG_GPIO_WRITE		0x1F
46a5f8c7daSStefan Popa #define AD7768_REG_GPIO_READ		0x20
47a5f8c7daSStefan Popa #define AD7768_REG_OFFSET_HI		0x21
48a5f8c7daSStefan Popa #define AD7768_REG_OFFSET_MID		0x22
49a5f8c7daSStefan Popa #define AD7768_REG_OFFSET_LO		0x23
50a5f8c7daSStefan Popa #define AD7768_REG_GAIN_HI		0x24
51a5f8c7daSStefan Popa #define AD7768_REG_GAIN_MID		0x25
52a5f8c7daSStefan Popa #define AD7768_REG_GAIN_LO		0x26
53a5f8c7daSStefan Popa #define AD7768_REG_SPI_DIAG_ENABLE	0x28
54a5f8c7daSStefan Popa #define AD7768_REG_ADC_DIAG_ENABLE	0x29
55a5f8c7daSStefan Popa #define AD7768_REG_DIG_DIAG_ENABLE	0x2A
56a5f8c7daSStefan Popa #define AD7768_REG_ADC_DATA		0x2C
57a5f8c7daSStefan Popa #define AD7768_REG_MASTER_STATUS	0x2D
58a5f8c7daSStefan Popa #define AD7768_REG_SPI_DIAG_STATUS	0x2E
59a5f8c7daSStefan Popa #define AD7768_REG_ADC_DIAG_STATUS	0x2F
60a5f8c7daSStefan Popa #define AD7768_REG_DIG_DIAG_STATUS	0x30
61a5f8c7daSStefan Popa #define AD7768_REG_MCLK_COUNTER		0x31
62a5f8c7daSStefan Popa 
63e9517dffSStefan Popa /* AD7768_REG_POWER_CLOCK */
64e9517dffSStefan Popa #define AD7768_PWR_MCLK_DIV_MSK		GENMASK(5, 4)
65e9517dffSStefan Popa #define AD7768_PWR_MCLK_DIV(x)		FIELD_PREP(AD7768_PWR_MCLK_DIV_MSK, x)
66e9517dffSStefan Popa #define AD7768_PWR_PWRMODE_MSK		GENMASK(1, 0)
67e9517dffSStefan Popa #define AD7768_PWR_PWRMODE(x)		FIELD_PREP(AD7768_PWR_PWRMODE_MSK, x)
68e9517dffSStefan Popa 
69e9517dffSStefan Popa /* AD7768_REG_DIGITAL_FILTER */
70e9517dffSStefan Popa #define AD7768_DIG_FIL_FIL_MSK		GENMASK(6, 4)
71e9517dffSStefan Popa #define AD7768_DIG_FIL_FIL(x)		FIELD_PREP(AD7768_DIG_FIL_FIL_MSK, x)
72e9517dffSStefan Popa #define AD7768_DIG_FIL_DEC_MSK		GENMASK(2, 0)
73e9517dffSStefan Popa #define AD7768_DIG_FIL_DEC_RATE(x)	FIELD_PREP(AD7768_DIG_FIL_DEC_MSK, x)
74e9517dffSStefan Popa 
75a5f8c7daSStefan Popa /* AD7768_REG_CONVERSION */
76a5f8c7daSStefan Popa #define AD7768_CONV_MODE_MSK		GENMASK(2, 0)
77a5f8c7daSStefan Popa #define AD7768_CONV_MODE(x)		FIELD_PREP(AD7768_CONV_MODE_MSK, x)
78a5f8c7daSStefan Popa 
79a5f8c7daSStefan Popa #define AD7768_RD_FLAG_MSK(x)		(BIT(6) | ((x) & 0x3F))
80a5f8c7daSStefan Popa #define AD7768_WR_FLAG_MSK(x)		((x) & 0x3F)
81a5f8c7daSStefan Popa 
82a5f8c7daSStefan Popa enum ad7768_conv_mode {
83a5f8c7daSStefan Popa 	AD7768_CONTINUOUS,
84a5f8c7daSStefan Popa 	AD7768_ONE_SHOT,
85a5f8c7daSStefan Popa 	AD7768_SINGLE,
86a5f8c7daSStefan Popa 	AD7768_PERIODIC,
87a5f8c7daSStefan Popa 	AD7768_STANDBY
88a5f8c7daSStefan Popa };
89a5f8c7daSStefan Popa 
90a5f8c7daSStefan Popa enum ad7768_pwrmode {
91a5f8c7daSStefan Popa 	AD7768_ECO_MODE = 0,
92a5f8c7daSStefan Popa 	AD7768_MED_MODE = 2,
93a5f8c7daSStefan Popa 	AD7768_FAST_MODE = 3
94a5f8c7daSStefan Popa };
95a5f8c7daSStefan Popa 
96e9517dffSStefan Popa enum ad7768_mclk_div {
97e9517dffSStefan Popa 	AD7768_MCLK_DIV_16,
98e9517dffSStefan Popa 	AD7768_MCLK_DIV_8,
99e9517dffSStefan Popa 	AD7768_MCLK_DIV_4,
100e9517dffSStefan Popa 	AD7768_MCLK_DIV_2
101e9517dffSStefan Popa };
102e9517dffSStefan Popa 
103e9517dffSStefan Popa enum ad7768_dec_rate {
104e9517dffSStefan Popa 	AD7768_DEC_RATE_32 = 0,
105e9517dffSStefan Popa 	AD7768_DEC_RATE_64 = 1,
106e9517dffSStefan Popa 	AD7768_DEC_RATE_128 = 2,
107e9517dffSStefan Popa 	AD7768_DEC_RATE_256 = 3,
108e9517dffSStefan Popa 	AD7768_DEC_RATE_512 = 4,
109e9517dffSStefan Popa 	AD7768_DEC_RATE_1024 = 5,
110e9517dffSStefan Popa 	AD7768_DEC_RATE_8 = 9,
111e9517dffSStefan Popa 	AD7768_DEC_RATE_16 = 10
112e9517dffSStefan Popa };
113e9517dffSStefan Popa 
114e9517dffSStefan Popa struct ad7768_clk_configuration {
115e9517dffSStefan Popa 	enum ad7768_mclk_div mclk_div;
116e9517dffSStefan Popa 	enum ad7768_dec_rate dec_rate;
117e9517dffSStefan Popa 	unsigned int clk_div;
118e9517dffSStefan Popa 	enum ad7768_pwrmode pwrmode;
119e9517dffSStefan Popa };
120e9517dffSStefan Popa 
121e9517dffSStefan Popa static const struct ad7768_clk_configuration ad7768_clk_config[] = {
122e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_2, AD7768_DEC_RATE_8, 16,  AD7768_FAST_MODE },
123e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_2, AD7768_DEC_RATE_16, 32,  AD7768_FAST_MODE },
124e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_2, AD7768_DEC_RATE_32, 64, AD7768_FAST_MODE },
125e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_2, AD7768_DEC_RATE_64, 128, AD7768_FAST_MODE },
126e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_2, AD7768_DEC_RATE_128, 256, AD7768_FAST_MODE },
127e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_4, AD7768_DEC_RATE_128, 512, AD7768_MED_MODE },
128e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_4, AD7768_DEC_RATE_256, 1024, AD7768_MED_MODE },
129e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_4, AD7768_DEC_RATE_512, 2048, AD7768_MED_MODE },
130e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_4, AD7768_DEC_RATE_1024, 4096, AD7768_MED_MODE },
131e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_8, AD7768_DEC_RATE_1024, 8192, AD7768_MED_MODE },
132e9517dffSStefan Popa 	{ AD7768_MCLK_DIV_16, AD7768_DEC_RATE_1024, 16384, AD7768_ECO_MODE },
133e9517dffSStefan Popa };
134e9517dffSStefan Popa 
135a5f8c7daSStefan Popa static const struct iio_chan_spec ad7768_channels[] = {
136a5f8c7daSStefan Popa 	{
137a5f8c7daSStefan Popa 		.type = IIO_VOLTAGE,
138a5f8c7daSStefan Popa 		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
139a5f8c7daSStefan Popa 		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
140e9517dffSStefan Popa 		.info_mask_shared_by_all = BIT(IIO_CHAN_INFO_SAMP_FREQ),
141a5f8c7daSStefan Popa 		.indexed = 1,
142a5f8c7daSStefan Popa 		.channel = 0,
143a5f8c7daSStefan Popa 		.scan_index = 0,
144a5f8c7daSStefan Popa 		.scan_type = {
145a5f8c7daSStefan Popa 			.sign = 'u',
146a5f8c7daSStefan Popa 			.realbits = 24,
147a5f8c7daSStefan Popa 			.storagebits = 32,
148a5f8c7daSStefan Popa 			.shift = 8,
149a5f8c7daSStefan Popa 			.endianness = IIO_BE,
150a5f8c7daSStefan Popa 		},
151a5f8c7daSStefan Popa 	},
152a5f8c7daSStefan Popa };
153a5f8c7daSStefan Popa 
154a5f8c7daSStefan Popa struct ad7768_state {
155a5f8c7daSStefan Popa 	struct spi_device *spi;
156a5f8c7daSStefan Popa 	struct regulator *vref;
157a5f8c7daSStefan Popa 	struct mutex lock;
158e9517dffSStefan Popa 	struct clk *mclk;
159e9517dffSStefan Popa 	unsigned int mclk_freq;
160e9517dffSStefan Popa 	unsigned int samp_freq;
161a5f8c7daSStefan Popa 	struct completion completion;
162a5f8c7daSStefan Popa 	struct iio_trigger *trig;
163e9517dffSStefan Popa 	struct gpio_desc *gpio_sync_in;
16475ed0be7SCristian Pop 	const char *labels[ARRAY_SIZE(ad7768_channels)];
165a5f8c7daSStefan Popa 	/*
166211f810fSJonathan Cameron 	 * DMA (thus cache coherency maintenance) may require the
167a5f8c7daSStefan Popa 	 * transfer buffers to live in their own cache lines.
168a5f8c7daSStefan Popa 	 */
169a5f8c7daSStefan Popa 	union {
170a1caeebaSJonathan Cameron 		struct {
171a1caeebaSJonathan Cameron 			__be32 chan;
172a1caeebaSJonathan Cameron 			s64 timestamp;
173a1caeebaSJonathan Cameron 		} scan;
174a5f8c7daSStefan Popa 		__be32 d32;
175a5f8c7daSStefan Popa 		u8 d8[2];
176211f810fSJonathan Cameron 	} data __aligned(IIO_DMA_MINALIGN);
177a5f8c7daSStefan Popa };
178a5f8c7daSStefan Popa 
ad7768_spi_reg_read(struct ad7768_state * st,unsigned int addr,unsigned int len)179a5f8c7daSStefan Popa static int ad7768_spi_reg_read(struct ad7768_state *st, unsigned int addr,
180a5f8c7daSStefan Popa 			       unsigned int len)
181a5f8c7daSStefan Popa {
182a5f8c7daSStefan Popa 	unsigned int shift;
183a5f8c7daSStefan Popa 	int ret;
184a5f8c7daSStefan Popa 
185a5f8c7daSStefan Popa 	shift = 32 - (8 * len);
186a5f8c7daSStefan Popa 	st->data.d8[0] = AD7768_RD_FLAG_MSK(addr);
187a5f8c7daSStefan Popa 
188a5f8c7daSStefan Popa 	ret = spi_write_then_read(st->spi, st->data.d8, 1,
189a5f8c7daSStefan Popa 				  &st->data.d32, len);
190a5f8c7daSStefan Popa 	if (ret < 0)
191a5f8c7daSStefan Popa 		return ret;
192a5f8c7daSStefan Popa 
193a5f8c7daSStefan Popa 	return (be32_to_cpu(st->data.d32) >> shift);
194a5f8c7daSStefan Popa }
195a5f8c7daSStefan Popa 
ad7768_spi_reg_write(struct ad7768_state * st,unsigned int addr,unsigned int val)196a5f8c7daSStefan Popa static int ad7768_spi_reg_write(struct ad7768_state *st,
197a5f8c7daSStefan Popa 				unsigned int addr,
198a5f8c7daSStefan Popa 				unsigned int val)
199a5f8c7daSStefan Popa {
200a5f8c7daSStefan Popa 	st->data.d8[0] = AD7768_WR_FLAG_MSK(addr);
201a5f8c7daSStefan Popa 	st->data.d8[1] = val & 0xFF;
202a5f8c7daSStefan Popa 
203a5f8c7daSStefan Popa 	return spi_write(st->spi, st->data.d8, 2);
204a5f8c7daSStefan Popa }
205a5f8c7daSStefan Popa 
ad7768_set_mode(struct ad7768_state * st,enum ad7768_conv_mode mode)206a5f8c7daSStefan Popa static int ad7768_set_mode(struct ad7768_state *st,
207a5f8c7daSStefan Popa 			   enum ad7768_conv_mode mode)
208a5f8c7daSStefan Popa {
209a5f8c7daSStefan Popa 	int regval;
210a5f8c7daSStefan Popa 
211a5f8c7daSStefan Popa 	regval = ad7768_spi_reg_read(st, AD7768_REG_CONVERSION, 1);
212a5f8c7daSStefan Popa 	if (regval < 0)
213a5f8c7daSStefan Popa 		return regval;
214a5f8c7daSStefan Popa 
215a5f8c7daSStefan Popa 	regval &= ~AD7768_CONV_MODE_MSK;
216a5f8c7daSStefan Popa 	regval |= AD7768_CONV_MODE(mode);
217a5f8c7daSStefan Popa 
218a5f8c7daSStefan Popa 	return ad7768_spi_reg_write(st, AD7768_REG_CONVERSION, regval);
219a5f8c7daSStefan Popa }
220a5f8c7daSStefan Popa 
ad7768_scan_direct(struct iio_dev * indio_dev)221a5f8c7daSStefan Popa static int ad7768_scan_direct(struct iio_dev *indio_dev)
222a5f8c7daSStefan Popa {
223a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
224a5f8c7daSStefan Popa 	int readval, ret;
225a5f8c7daSStefan Popa 
226a5f8c7daSStefan Popa 	reinit_completion(&st->completion);
227a5f8c7daSStefan Popa 
228a5f8c7daSStefan Popa 	ret = ad7768_set_mode(st, AD7768_ONE_SHOT);
229a5f8c7daSStefan Popa 	if (ret < 0)
230a5f8c7daSStefan Popa 		return ret;
231a5f8c7daSStefan Popa 
232a5f8c7daSStefan Popa 	ret = wait_for_completion_timeout(&st->completion,
233a5f8c7daSStefan Popa 					  msecs_to_jiffies(1000));
234a5f8c7daSStefan Popa 	if (!ret)
235a5f8c7daSStefan Popa 		return -ETIMEDOUT;
236a5f8c7daSStefan Popa 
237a5f8c7daSStefan Popa 	readval = ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
238a5f8c7daSStefan Popa 	if (readval < 0)
239a5f8c7daSStefan Popa 		return readval;
240a5f8c7daSStefan Popa 	/*
241a5f8c7daSStefan Popa 	 * Any SPI configuration of the AD7768-1 can only be
242a5f8c7daSStefan Popa 	 * performed in continuous conversion mode.
243a5f8c7daSStefan Popa 	 */
244a5f8c7daSStefan Popa 	ret = ad7768_set_mode(st, AD7768_CONTINUOUS);
245a5f8c7daSStefan Popa 	if (ret < 0)
246a5f8c7daSStefan Popa 		return ret;
247a5f8c7daSStefan Popa 
248a5f8c7daSStefan Popa 	return readval;
249a5f8c7daSStefan Popa }
250a5f8c7daSStefan Popa 
ad7768_reg_access(struct iio_dev * indio_dev,unsigned int reg,unsigned int writeval,unsigned int * readval)251a5f8c7daSStefan Popa static int ad7768_reg_access(struct iio_dev *indio_dev,
252a5f8c7daSStefan Popa 			     unsigned int reg,
253a5f8c7daSStefan Popa 			     unsigned int writeval,
254a5f8c7daSStefan Popa 			     unsigned int *readval)
255a5f8c7daSStefan Popa {
256a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
257a5f8c7daSStefan Popa 	int ret;
258a5f8c7daSStefan Popa 
259a5f8c7daSStefan Popa 	mutex_lock(&st->lock);
260a5f8c7daSStefan Popa 	if (readval) {
261a5f8c7daSStefan Popa 		ret = ad7768_spi_reg_read(st, reg, 1);
262a5f8c7daSStefan Popa 		if (ret < 0)
263a5f8c7daSStefan Popa 			goto err_unlock;
264a5f8c7daSStefan Popa 		*readval = ret;
265a5f8c7daSStefan Popa 		ret = 0;
266a5f8c7daSStefan Popa 	} else {
267a5f8c7daSStefan Popa 		ret = ad7768_spi_reg_write(st, reg, writeval);
268a5f8c7daSStefan Popa 	}
269a5f8c7daSStefan Popa err_unlock:
270a5f8c7daSStefan Popa 	mutex_unlock(&st->lock);
271a5f8c7daSStefan Popa 
272a5f8c7daSStefan Popa 	return ret;
273a5f8c7daSStefan Popa }
274a5f8c7daSStefan Popa 
ad7768_set_dig_fil(struct ad7768_state * st,enum ad7768_dec_rate dec_rate)275e9517dffSStefan Popa static int ad7768_set_dig_fil(struct ad7768_state *st,
276e9517dffSStefan Popa 			      enum ad7768_dec_rate dec_rate)
277e9517dffSStefan Popa {
278e9517dffSStefan Popa 	unsigned int mode;
279e9517dffSStefan Popa 	int ret;
280e9517dffSStefan Popa 
281e9517dffSStefan Popa 	if (dec_rate == AD7768_DEC_RATE_8 || dec_rate == AD7768_DEC_RATE_16)
282e9517dffSStefan Popa 		mode = AD7768_DIG_FIL_FIL(dec_rate);
283e9517dffSStefan Popa 	else
284e9517dffSStefan Popa 		mode = AD7768_DIG_FIL_DEC_RATE(dec_rate);
285e9517dffSStefan Popa 
286e9517dffSStefan Popa 	ret = ad7768_spi_reg_write(st, AD7768_REG_DIGITAL_FILTER, mode);
287e9517dffSStefan Popa 	if (ret < 0)
288e9517dffSStefan Popa 		return ret;
289e9517dffSStefan Popa 
290e9517dffSStefan Popa 	/* A sync-in pulse is required every time the filter dec rate changes */
291e9517dffSStefan Popa 	gpiod_set_value(st->gpio_sync_in, 1);
292e9517dffSStefan Popa 	gpiod_set_value(st->gpio_sync_in, 0);
293e9517dffSStefan Popa 
294e9517dffSStefan Popa 	return 0;
295e9517dffSStefan Popa }
296e9517dffSStefan Popa 
ad7768_set_freq(struct ad7768_state * st,unsigned int freq)297e9517dffSStefan Popa static int ad7768_set_freq(struct ad7768_state *st,
298e9517dffSStefan Popa 			   unsigned int freq)
299e9517dffSStefan Popa {
300e9517dffSStefan Popa 	unsigned int diff_new, diff_old, pwr_mode, i, idx;
301e9517dffSStefan Popa 	int res, ret;
302e9517dffSStefan Popa 
303e9517dffSStefan Popa 	diff_old = U32_MAX;
304e9517dffSStefan Popa 	idx = 0;
305e9517dffSStefan Popa 
306e9517dffSStefan Popa 	res = DIV_ROUND_CLOSEST(st->mclk_freq, freq);
307e9517dffSStefan Popa 
308e9517dffSStefan Popa 	/* Find the closest match for the desired sampling frequency */
309e9517dffSStefan Popa 	for (i = 0; i < ARRAY_SIZE(ad7768_clk_config); i++) {
310e9517dffSStefan Popa 		diff_new = abs(res - ad7768_clk_config[i].clk_div);
311e9517dffSStefan Popa 		if (diff_new < diff_old) {
312e9517dffSStefan Popa 			diff_old = diff_new;
313e9517dffSStefan Popa 			idx = i;
314e9517dffSStefan Popa 		}
315e9517dffSStefan Popa 	}
316e9517dffSStefan Popa 
317e9517dffSStefan Popa 	/*
318e9517dffSStefan Popa 	 * Set both the mclk_div and pwrmode with a single write to the
319e9517dffSStefan Popa 	 * POWER_CLOCK register
320e9517dffSStefan Popa 	 */
321e9517dffSStefan Popa 	pwr_mode = AD7768_PWR_MCLK_DIV(ad7768_clk_config[idx].mclk_div) |
322e9517dffSStefan Popa 		   AD7768_PWR_PWRMODE(ad7768_clk_config[idx].pwrmode);
323e9517dffSStefan Popa 	ret = ad7768_spi_reg_write(st, AD7768_REG_POWER_CLOCK, pwr_mode);
324e9517dffSStefan Popa 	if (ret < 0)
325e9517dffSStefan Popa 		return ret;
326e9517dffSStefan Popa 
327e9517dffSStefan Popa 	ret =  ad7768_set_dig_fil(st, ad7768_clk_config[idx].dec_rate);
328e9517dffSStefan Popa 	if (ret < 0)
329e9517dffSStefan Popa 		return ret;
330e9517dffSStefan Popa 
331e9517dffSStefan Popa 	st->samp_freq = DIV_ROUND_CLOSEST(st->mclk_freq,
332e9517dffSStefan Popa 					  ad7768_clk_config[idx].clk_div);
333e9517dffSStefan Popa 
334e9517dffSStefan Popa 	return 0;
335e9517dffSStefan Popa }
336e9517dffSStefan Popa 
ad7768_sampling_freq_avail(struct device * dev,struct device_attribute * attr,char * buf)337e9517dffSStefan Popa static ssize_t ad7768_sampling_freq_avail(struct device *dev,
338e9517dffSStefan Popa 					  struct device_attribute *attr,
339e9517dffSStefan Popa 					  char *buf)
340e9517dffSStefan Popa {
341e9517dffSStefan Popa 	struct iio_dev *indio_dev = dev_to_iio_dev(dev);
342e9517dffSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
343e9517dffSStefan Popa 	unsigned int freq;
344e9517dffSStefan Popa 	int i, len = 0;
345e9517dffSStefan Popa 
346e9517dffSStefan Popa 	for (i = 0; i < ARRAY_SIZE(ad7768_clk_config); i++) {
347e9517dffSStefan Popa 		freq = DIV_ROUND_CLOSEST(st->mclk_freq,
348e9517dffSStefan Popa 					 ad7768_clk_config[i].clk_div);
349e9517dffSStefan Popa 		len += scnprintf(buf + len, PAGE_SIZE - len, "%d ", freq);
350e9517dffSStefan Popa 	}
351e9517dffSStefan Popa 
352e9517dffSStefan Popa 	buf[len - 1] = '\n';
353e9517dffSStefan Popa 
354e9517dffSStefan Popa 	return len;
355e9517dffSStefan Popa }
356e9517dffSStefan Popa 
357e9517dffSStefan Popa static IIO_DEV_ATTR_SAMP_FREQ_AVAIL(ad7768_sampling_freq_avail);
358e9517dffSStefan Popa 
ad7768_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long info)359a5f8c7daSStefan Popa static int ad7768_read_raw(struct iio_dev *indio_dev,
360a5f8c7daSStefan Popa 			   struct iio_chan_spec const *chan,
361a5f8c7daSStefan Popa 			   int *val, int *val2, long info)
362a5f8c7daSStefan Popa {
363a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
364a5f8c7daSStefan Popa 	int scale_uv, ret;
365a5f8c7daSStefan Popa 
366a5f8c7daSStefan Popa 	switch (info) {
367a5f8c7daSStefan Popa 	case IIO_CHAN_INFO_RAW:
368a5f8c7daSStefan Popa 		ret = iio_device_claim_direct_mode(indio_dev);
369a5f8c7daSStefan Popa 		if (ret)
370a5f8c7daSStefan Popa 			return ret;
371a5f8c7daSStefan Popa 
372a5f8c7daSStefan Popa 		ret = ad7768_scan_direct(indio_dev);
373a5f8c7daSStefan Popa 		if (ret >= 0)
374a5f8c7daSStefan Popa 			*val = ret;
375a5f8c7daSStefan Popa 
376a5f8c7daSStefan Popa 		iio_device_release_direct_mode(indio_dev);
377a5f8c7daSStefan Popa 		if (ret < 0)
378a5f8c7daSStefan Popa 			return ret;
379a5f8c7daSStefan Popa 
380a5f8c7daSStefan Popa 		return IIO_VAL_INT;
381a5f8c7daSStefan Popa 
382a5f8c7daSStefan Popa 	case IIO_CHAN_INFO_SCALE:
383a5f8c7daSStefan Popa 		scale_uv = regulator_get_voltage(st->vref);
384a5f8c7daSStefan Popa 		if (scale_uv < 0)
385a5f8c7daSStefan Popa 			return scale_uv;
386a5f8c7daSStefan Popa 
387a5f8c7daSStefan Popa 		*val = (scale_uv * 2) / 1000;
388a5f8c7daSStefan Popa 		*val2 = chan->scan_type.realbits;
389a5f8c7daSStefan Popa 
390a5f8c7daSStefan Popa 		return IIO_VAL_FRACTIONAL_LOG2;
391e9517dffSStefan Popa 
392e9517dffSStefan Popa 	case IIO_CHAN_INFO_SAMP_FREQ:
393e9517dffSStefan Popa 		*val = st->samp_freq;
394e9517dffSStefan Popa 
395e9517dffSStefan Popa 		return IIO_VAL_INT;
396a5f8c7daSStefan Popa 	}
397a5f8c7daSStefan Popa 
398a5f8c7daSStefan Popa 	return -EINVAL;
399a5f8c7daSStefan Popa }
400a5f8c7daSStefan Popa 
ad7768_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long info)401e9517dffSStefan Popa static int ad7768_write_raw(struct iio_dev *indio_dev,
402e9517dffSStefan Popa 			    struct iio_chan_spec const *chan,
403e9517dffSStefan Popa 			    int val, int val2, long info)
404e9517dffSStefan Popa {
405e9517dffSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
406e9517dffSStefan Popa 
407e9517dffSStefan Popa 	switch (info) {
408e9517dffSStefan Popa 	case IIO_CHAN_INFO_SAMP_FREQ:
409e9517dffSStefan Popa 		return ad7768_set_freq(st, val);
410e9517dffSStefan Popa 	default:
411e9517dffSStefan Popa 		return -EINVAL;
412e9517dffSStefan Popa 	}
413e9517dffSStefan Popa }
414e9517dffSStefan Popa 
ad7768_read_label(struct iio_dev * indio_dev,const struct iio_chan_spec * chan,char * label)41575ed0be7SCristian Pop static int ad7768_read_label(struct iio_dev *indio_dev,
41675ed0be7SCristian Pop 	const struct iio_chan_spec *chan, char *label)
41775ed0be7SCristian Pop {
41875ed0be7SCristian Pop 	struct ad7768_state *st = iio_priv(indio_dev);
41975ed0be7SCristian Pop 
42075ed0be7SCristian Pop 	return sprintf(label, "%s\n", st->labels[chan->channel]);
42175ed0be7SCristian Pop }
42275ed0be7SCristian Pop 
423e9517dffSStefan Popa static struct attribute *ad7768_attributes[] = {
424e9517dffSStefan Popa 	&iio_dev_attr_sampling_frequency_available.dev_attr.attr,
425e9517dffSStefan Popa 	NULL
426e9517dffSStefan Popa };
427e9517dffSStefan Popa 
428e9517dffSStefan Popa static const struct attribute_group ad7768_group = {
429e9517dffSStefan Popa 	.attrs = ad7768_attributes,
430e9517dffSStefan Popa };
431e9517dffSStefan Popa 
432a5f8c7daSStefan Popa static const struct iio_info ad7768_info = {
433e9517dffSStefan Popa 	.attrs = &ad7768_group,
434a5f8c7daSStefan Popa 	.read_raw = &ad7768_read_raw,
435e9517dffSStefan Popa 	.write_raw = &ad7768_write_raw,
43675ed0be7SCristian Pop 	.read_label = ad7768_read_label,
437a5f8c7daSStefan Popa 	.debugfs_reg_access = &ad7768_reg_access,
438a5f8c7daSStefan Popa };
439a5f8c7daSStefan Popa 
ad7768_setup(struct ad7768_state * st)440a5f8c7daSStefan Popa static int ad7768_setup(struct ad7768_state *st)
441a5f8c7daSStefan Popa {
442a5f8c7daSStefan Popa 	int ret;
443a5f8c7daSStefan Popa 
444a5f8c7daSStefan Popa 	/*
445a5f8c7daSStefan Popa 	 * Two writes to the SPI_RESET[1:0] bits are required to initiate
446a5f8c7daSStefan Popa 	 * a software reset. The bits must first be set to 11, and then
447a5f8c7daSStefan Popa 	 * to 10. When the sequence is detected, the reset occurs.
448a5f8c7daSStefan Popa 	 * See the datasheet, page 70.
449a5f8c7daSStefan Popa 	 */
450a5f8c7daSStefan Popa 	ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x3);
451a5f8c7daSStefan Popa 	if (ret)
452a5f8c7daSStefan Popa 		return ret;
453a5f8c7daSStefan Popa 
454a5f8c7daSStefan Popa 	ret = ad7768_spi_reg_write(st, AD7768_REG_SYNC_RESET, 0x2);
455a5f8c7daSStefan Popa 	if (ret)
456a5f8c7daSStefan Popa 		return ret;
457a5f8c7daSStefan Popa 
458e9517dffSStefan Popa 	st->gpio_sync_in = devm_gpiod_get(&st->spi->dev, "adi,sync-in",
459e9517dffSStefan Popa 					  GPIOD_OUT_LOW);
460e9517dffSStefan Popa 	if (IS_ERR(st->gpio_sync_in))
461e9517dffSStefan Popa 		return PTR_ERR(st->gpio_sync_in);
462e9517dffSStefan Popa 
463e9517dffSStefan Popa 	/* Set the default sampling frequency to 32000 kSPS */
464e9517dffSStefan Popa 	return ad7768_set_freq(st, 32000);
465a5f8c7daSStefan Popa }
466a5f8c7daSStefan Popa 
ad7768_trigger_handler(int irq,void * p)467a5f8c7daSStefan Popa static irqreturn_t ad7768_trigger_handler(int irq, void *p)
468a5f8c7daSStefan Popa {
469a5f8c7daSStefan Popa 	struct iio_poll_func *pf = p;
470a5f8c7daSStefan Popa 	struct iio_dev *indio_dev = pf->indio_dev;
471a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
472a5f8c7daSStefan Popa 	int ret;
473a5f8c7daSStefan Popa 
474a5f8c7daSStefan Popa 	mutex_lock(&st->lock);
475a5f8c7daSStefan Popa 
476a1caeebaSJonathan Cameron 	ret = spi_read(st->spi, &st->data.scan.chan, 3);
477a5f8c7daSStefan Popa 	if (ret < 0)
478a5f8c7daSStefan Popa 		goto err_unlock;
479a5f8c7daSStefan Popa 
480a1caeebaSJonathan Cameron 	iio_push_to_buffers_with_timestamp(indio_dev, &st->data.scan,
481a5f8c7daSStefan Popa 					   iio_get_time_ns(indio_dev));
482a5f8c7daSStefan Popa 
483a5f8c7daSStefan Popa err_unlock:
48466611464SLars-Peter Clausen 	iio_trigger_notify_done(indio_dev->trig);
485a5f8c7daSStefan Popa 	mutex_unlock(&st->lock);
486a5f8c7daSStefan Popa 
487a5f8c7daSStefan Popa 	return IRQ_HANDLED;
488a5f8c7daSStefan Popa }
489a5f8c7daSStefan Popa 
ad7768_interrupt(int irq,void * dev_id)490a5f8c7daSStefan Popa static irqreturn_t ad7768_interrupt(int irq, void *dev_id)
491a5f8c7daSStefan Popa {
492a5f8c7daSStefan Popa 	struct iio_dev *indio_dev = dev_id;
493a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
494a5f8c7daSStefan Popa 
495a5f8c7daSStefan Popa 	if (iio_buffer_enabled(indio_dev))
496a5f8c7daSStefan Popa 		iio_trigger_poll(st->trig);
497a5f8c7daSStefan Popa 	else
498a5f8c7daSStefan Popa 		complete(&st->completion);
499a5f8c7daSStefan Popa 
500a5f8c7daSStefan Popa 	return IRQ_HANDLED;
501a5f8c7daSStefan Popa };
502a5f8c7daSStefan Popa 
ad7768_buffer_postenable(struct iio_dev * indio_dev)503a5f8c7daSStefan Popa static int ad7768_buffer_postenable(struct iio_dev *indio_dev)
504a5f8c7daSStefan Popa {
505a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
506a5f8c7daSStefan Popa 
507a5f8c7daSStefan Popa 	/*
508a5f8c7daSStefan Popa 	 * Write a 1 to the LSB of the INTERFACE_FORMAT register to enter
509a5f8c7daSStefan Popa 	 * continuous read mode. Subsequent data reads do not require an
510a5f8c7daSStefan Popa 	 * initial 8-bit write to query the ADC_DATA register.
511a5f8c7daSStefan Popa 	 */
512a5f8c7daSStefan Popa 	return ad7768_spi_reg_write(st, AD7768_REG_INTERFACE_FORMAT, 0x01);
513a5f8c7daSStefan Popa }
514a5f8c7daSStefan Popa 
ad7768_buffer_predisable(struct iio_dev * indio_dev)515a5f8c7daSStefan Popa static int ad7768_buffer_predisable(struct iio_dev *indio_dev)
516a5f8c7daSStefan Popa {
517a5f8c7daSStefan Popa 	struct ad7768_state *st = iio_priv(indio_dev);
518a5f8c7daSStefan Popa 
519a5f8c7daSStefan Popa 	/*
520a5f8c7daSStefan Popa 	 * To exit continuous read mode, perform a single read of the ADC_DATA
521a5f8c7daSStefan Popa 	 * reg (0x2C), which allows further configuration of the device.
522a5f8c7daSStefan Popa 	 */
523f11d59d8SLars-Peter Clausen 	return ad7768_spi_reg_read(st, AD7768_REG_ADC_DATA, 3);
524a5f8c7daSStefan Popa }
525a5f8c7daSStefan Popa 
526a5f8c7daSStefan Popa static const struct iio_buffer_setup_ops ad7768_buffer_ops = {
527a5f8c7daSStefan Popa 	.postenable = &ad7768_buffer_postenable,
528a5f8c7daSStefan Popa 	.predisable = &ad7768_buffer_predisable,
529a5f8c7daSStefan Popa };
530a5f8c7daSStefan Popa 
531a5f8c7daSStefan Popa static const struct iio_trigger_ops ad7768_trigger_ops = {
532a5f8c7daSStefan Popa 	.validate_device = iio_trigger_validate_own_device,
533a5f8c7daSStefan Popa };
534a5f8c7daSStefan Popa 
ad7768_regulator_disable(void * data)535a5f8c7daSStefan Popa static void ad7768_regulator_disable(void *data)
536a5f8c7daSStefan Popa {
537a5f8c7daSStefan Popa 	struct ad7768_state *st = data;
538a5f8c7daSStefan Popa 
539a5f8c7daSStefan Popa 	regulator_disable(st->vref);
540a5f8c7daSStefan Popa }
541a5f8c7daSStefan Popa 
ad7768_set_channel_label(struct iio_dev * indio_dev,int num_channels)54275ed0be7SCristian Pop static int ad7768_set_channel_label(struct iio_dev *indio_dev,
54375ed0be7SCristian Pop 						int num_channels)
54475ed0be7SCristian Pop {
54575ed0be7SCristian Pop 	struct ad7768_state *st = iio_priv(indio_dev);
54675ed0be7SCristian Pop 	struct device *device = indio_dev->dev.parent;
54775ed0be7SCristian Pop 	struct fwnode_handle *fwnode;
54875ed0be7SCristian Pop 	struct fwnode_handle *child;
54975ed0be7SCristian Pop 	const char *label;
55075ed0be7SCristian Pop 	int crt_ch = 0;
55175ed0be7SCristian Pop 
55275ed0be7SCristian Pop 	fwnode = dev_fwnode(device);
55375ed0be7SCristian Pop 	fwnode_for_each_child_node(fwnode, child) {
55475ed0be7SCristian Pop 		if (fwnode_property_read_u32(child, "reg", &crt_ch))
55575ed0be7SCristian Pop 			continue;
55675ed0be7SCristian Pop 
55775ed0be7SCristian Pop 		if (crt_ch >= num_channels)
55875ed0be7SCristian Pop 			continue;
55975ed0be7SCristian Pop 
56075ed0be7SCristian Pop 		if (fwnode_property_read_string(child, "label", &label))
56175ed0be7SCristian Pop 			continue;
56275ed0be7SCristian Pop 
56375ed0be7SCristian Pop 		st->labels[crt_ch] = label;
56475ed0be7SCristian Pop 	}
56575ed0be7SCristian Pop 
56675ed0be7SCristian Pop 	return 0;
56775ed0be7SCristian Pop }
56875ed0be7SCristian Pop 
ad7768_probe(struct spi_device * spi)569a5f8c7daSStefan Popa static int ad7768_probe(struct spi_device *spi)
570a5f8c7daSStefan Popa {
571a5f8c7daSStefan Popa 	struct ad7768_state *st;
572a5f8c7daSStefan Popa 	struct iio_dev *indio_dev;
573a5f8c7daSStefan Popa 	int ret;
574a5f8c7daSStefan Popa 
575a5f8c7daSStefan Popa 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
576a5f8c7daSStefan Popa 	if (!indio_dev)
577a5f8c7daSStefan Popa 		return -ENOMEM;
578a5f8c7daSStefan Popa 
579a5f8c7daSStefan Popa 	st = iio_priv(indio_dev);
580a5f8c7daSStefan Popa 	st->spi = spi;
581a5f8c7daSStefan Popa 
582a5f8c7daSStefan Popa 	st->vref = devm_regulator_get(&spi->dev, "vref");
583a5f8c7daSStefan Popa 	if (IS_ERR(st->vref))
584a5f8c7daSStefan Popa 		return PTR_ERR(st->vref);
585a5f8c7daSStefan Popa 
586a5f8c7daSStefan Popa 	ret = regulator_enable(st->vref);
587a5f8c7daSStefan Popa 	if (ret) {
588a5f8c7daSStefan Popa 		dev_err(&spi->dev, "Failed to enable specified vref supply\n");
589a5f8c7daSStefan Popa 		return ret;
590a5f8c7daSStefan Popa 	}
591a5f8c7daSStefan Popa 
592a5f8c7daSStefan Popa 	ret = devm_add_action_or_reset(&spi->dev, ad7768_regulator_disable, st);
593a5f8c7daSStefan Popa 	if (ret)
594a5f8c7daSStefan Popa 		return ret;
595a5f8c7daSStefan Popa 
596*25f7e795SUwe Kleine-König 	st->mclk = devm_clk_get_enabled(&spi->dev, "mclk");
597e9517dffSStefan Popa 	if (IS_ERR(st->mclk))
598e9517dffSStefan Popa 		return PTR_ERR(st->mclk);
599e9517dffSStefan Popa 
600e9517dffSStefan Popa 	st->mclk_freq = clk_get_rate(st->mclk);
601e9517dffSStefan Popa 
602a5f8c7daSStefan Popa 	mutex_init(&st->lock);
603a5f8c7daSStefan Popa 
604a5f8c7daSStefan Popa 	indio_dev->channels = ad7768_channels;
605a5f8c7daSStefan Popa 	indio_dev->num_channels = ARRAY_SIZE(ad7768_channels);
606a5f8c7daSStefan Popa 	indio_dev->name = spi_get_device_id(spi)->name;
607a5f8c7daSStefan Popa 	indio_dev->info = &ad7768_info;
608bca036deSMarcus Folkesson 	indio_dev->modes = INDIO_DIRECT_MODE;
609a5f8c7daSStefan Popa 
610a5f8c7daSStefan Popa 	ret = ad7768_setup(st);
611a5f8c7daSStefan Popa 	if (ret < 0) {
612a5f8c7daSStefan Popa 		dev_err(&spi->dev, "AD7768 setup failed\n");
613a5f8c7daSStefan Popa 		return ret;
614a5f8c7daSStefan Popa 	}
615a5f8c7daSStefan Popa 
616a5f8c7daSStefan Popa 	st->trig = devm_iio_trigger_alloc(&spi->dev, "%s-dev%d",
61715ea2878SJonathan Cameron 					  indio_dev->name,
61815ea2878SJonathan Cameron 					  iio_device_id(indio_dev));
619a5f8c7daSStefan Popa 	if (!st->trig)
620a5f8c7daSStefan Popa 		return -ENOMEM;
621a5f8c7daSStefan Popa 
622a5f8c7daSStefan Popa 	st->trig->ops = &ad7768_trigger_ops;
623a5f8c7daSStefan Popa 	iio_trigger_set_drvdata(st->trig, indio_dev);
624a5f8c7daSStefan Popa 	ret = devm_iio_trigger_register(&spi->dev, st->trig);
625a5f8c7daSStefan Popa 	if (ret)
626a5f8c7daSStefan Popa 		return ret;
627a5f8c7daSStefan Popa 
628a5f8c7daSStefan Popa 	indio_dev->trig = iio_trigger_get(st->trig);
629a5f8c7daSStefan Popa 
630a5f8c7daSStefan Popa 	init_completion(&st->completion);
631a5f8c7daSStefan Popa 
63275ed0be7SCristian Pop 	ret = ad7768_set_channel_label(indio_dev, ARRAY_SIZE(ad7768_channels));
63375ed0be7SCristian Pop 	if (ret)
63475ed0be7SCristian Pop 		return ret;
63575ed0be7SCristian Pop 
636a5f8c7daSStefan Popa 	ret = devm_request_irq(&spi->dev, spi->irq,
637a5f8c7daSStefan Popa 			       &ad7768_interrupt,
638a5f8c7daSStefan Popa 			       IRQF_TRIGGER_RISING | IRQF_ONESHOT,
639a5f8c7daSStefan Popa 			       indio_dev->name, indio_dev);
640a5f8c7daSStefan Popa 	if (ret)
641a5f8c7daSStefan Popa 		return ret;
642a5f8c7daSStefan Popa 
643a5f8c7daSStefan Popa 	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
644a5f8c7daSStefan Popa 					      &iio_pollfunc_store_time,
645a5f8c7daSStefan Popa 					      &ad7768_trigger_handler,
646a5f8c7daSStefan Popa 					      &ad7768_buffer_ops);
647a5f8c7daSStefan Popa 	if (ret)
648a5f8c7daSStefan Popa 		return ret;
649a5f8c7daSStefan Popa 
650a5f8c7daSStefan Popa 	return devm_iio_device_register(&spi->dev, indio_dev);
651a5f8c7daSStefan Popa }
652a5f8c7daSStefan Popa 
653a5f8c7daSStefan Popa static const struct spi_device_id ad7768_id_table[] = {
654a5f8c7daSStefan Popa 	{ "ad7768-1", 0 },
655a5f8c7daSStefan Popa 	{}
656a5f8c7daSStefan Popa };
657a5f8c7daSStefan Popa MODULE_DEVICE_TABLE(spi, ad7768_id_table);
658a5f8c7daSStefan Popa 
659a5f8c7daSStefan Popa static const struct of_device_id ad7768_of_match[] = {
660a5f8c7daSStefan Popa 	{ .compatible = "adi,ad7768-1" },
661a5f8c7daSStefan Popa 	{ },
662a5f8c7daSStefan Popa };
663a5f8c7daSStefan Popa MODULE_DEVICE_TABLE(of, ad7768_of_match);
664a5f8c7daSStefan Popa 
665a5f8c7daSStefan Popa static struct spi_driver ad7768_driver = {
666a5f8c7daSStefan Popa 	.driver = {
667a5f8c7daSStefan Popa 		.name = "ad7768-1",
668a5f8c7daSStefan Popa 		.of_match_table = ad7768_of_match,
669a5f8c7daSStefan Popa 	},
670a5f8c7daSStefan Popa 	.probe = ad7768_probe,
671a5f8c7daSStefan Popa 	.id_table = ad7768_id_table,
672a5f8c7daSStefan Popa };
673a5f8c7daSStefan Popa module_spi_driver(ad7768_driver);
674a5f8c7daSStefan Popa 
675a5f8c7daSStefan Popa MODULE_AUTHOR("Stefan Popa <stefan.popa@analog.com>");
676a5f8c7daSStefan Popa MODULE_DESCRIPTION("Analog Devices AD7768-1 ADC driver");
677a5f8c7daSStefan Popa MODULE_LICENSE("GPL v2");
678