xref: /openbmc/linux/drivers/iio/amplifiers/ad8366.c (revision c900529f3d9161bfde5cca0754f83b4d3c3e0220)
138ffa3a3SAlexandru Ardelean // SPDX-License-Identifier: GPL-2.0
2e71d42e0SMichael Hennerich /*
3cee211f4SPaul Cercueil  * AD8366 and similar Gain Amplifiers
4cee211f4SPaul Cercueil  * This driver supports the following gain amplifiers:
5cee211f4SPaul Cercueil  *   AD8366 Dual-Digital Variable Gain Amplifier (VGA)
6cee211f4SPaul Cercueil  *   ADA4961 BiCMOS RF Digital Gain Amplifier (DGA)
7075da9cdSAlexandru Ardelean  *   ADL5240 Digitally controlled variable gain amplifier (VGA)
8*247d3b63SKim Seer Paller  *   HMC792A 0.25 dB LSB GaAs MMIC 6-Bit Digital Attenuator
9cc74a38dSSergiu Cuciurean  *   HMC1119 0.25 dB LSB, 7-Bit, Silicon Digital Attenuator
10e71d42e0SMichael Hennerich  *
1138ffa3a3SAlexandru Ardelean  * Copyright 2012-2019 Analog Devices Inc.
12e71d42e0SMichael Hennerich  */
13e71d42e0SMichael Hennerich 
14e71d42e0SMichael Hennerich #include <linux/device.h>
15e71d42e0SMichael Hennerich #include <linux/kernel.h>
16e71d42e0SMichael Hennerich #include <linux/slab.h>
17e71d42e0SMichael Hennerich #include <linux/sysfs.h>
18e71d42e0SMichael Hennerich #include <linux/spi/spi.h>
19e71d42e0SMichael Hennerich #include <linux/regulator/consumer.h>
20cee211f4SPaul Cercueil #include <linux/gpio/consumer.h>
21e71d42e0SMichael Hennerich #include <linux/err.h>
22e71d42e0SMichael Hennerich #include <linux/module.h>
23e71d42e0SMichael Hennerich #include <linux/bitrev.h>
24e71d42e0SMichael Hennerich 
25e71d42e0SMichael Hennerich #include <linux/iio/iio.h>
26e71d42e0SMichael Hennerich #include <linux/iio/sysfs.h>
27e71d42e0SMichael Hennerich 
2811ab555aSAlexandru Ardelean enum ad8366_type {
2911ab555aSAlexandru Ardelean 	ID_AD8366,
30cee211f4SPaul Cercueil 	ID_ADA4961,
31075da9cdSAlexandru Ardelean 	ID_ADL5240,
32*247d3b63SKim Seer Paller 	ID_HMC792,
33cc74a38dSSergiu Cuciurean 	ID_HMC1119,
3411ab555aSAlexandru Ardelean };
3511ab555aSAlexandru Ardelean 
3611ab555aSAlexandru Ardelean struct ad8366_info {
3711ab555aSAlexandru Ardelean 	int gain_min;
3811ab555aSAlexandru Ardelean 	int gain_max;
3911ab555aSAlexandru Ardelean };
4011ab555aSAlexandru Ardelean 
41e71d42e0SMichael Hennerich struct ad8366_state {
42e71d42e0SMichael Hennerich 	struct spi_device	*spi;
43e71d42e0SMichael Hennerich 	struct regulator	*reg;
44dbcf6b5dSAlexandru Ardelean 	struct mutex            lock; /* protect sensor state */
45cee211f4SPaul Cercueil 	struct gpio_desc	*reset_gpio;
46e71d42e0SMichael Hennerich 	unsigned char		ch[2];
4711ab555aSAlexandru Ardelean 	enum ad8366_type	type;
4811ab555aSAlexandru Ardelean 	struct ad8366_info	*info;
49e71d42e0SMichael Hennerich 	/*
50026bffa4SJonathan Cameron 	 * DMA (thus cache coherency maintenance) may require the
51e71d42e0SMichael Hennerich 	 * transfer buffers to live in their own cache lines.
52e71d42e0SMichael Hennerich 	 */
53026bffa4SJonathan Cameron 	unsigned char		data[2] __aligned(IIO_DMA_MINALIGN);
54e71d42e0SMichael Hennerich };
55e71d42e0SMichael Hennerich 
5611ab555aSAlexandru Ardelean static struct ad8366_info ad8366_infos[] = {
5711ab555aSAlexandru Ardelean 	[ID_AD8366] = {
5811ab555aSAlexandru Ardelean 		.gain_min = 4500,
5911ab555aSAlexandru Ardelean 		.gain_max = 20500,
6011ab555aSAlexandru Ardelean 	},
61cee211f4SPaul Cercueil 	[ID_ADA4961] = {
62cee211f4SPaul Cercueil 		.gain_min = -6000,
63cee211f4SPaul Cercueil 		.gain_max = 15000,
64cee211f4SPaul Cercueil 	},
65075da9cdSAlexandru Ardelean 	[ID_ADL5240] = {
66075da9cdSAlexandru Ardelean 		.gain_min = -11500,
67075da9cdSAlexandru Ardelean 		.gain_max = 20000,
68075da9cdSAlexandru Ardelean 	},
69*247d3b63SKim Seer Paller 	[ID_HMC792] = {
70*247d3b63SKim Seer Paller 		.gain_min = -15750,
71*247d3b63SKim Seer Paller 		.gain_max = 0,
72*247d3b63SKim Seer Paller 	},
73cc74a38dSSergiu Cuciurean 	[ID_HMC1119] = {
74cc74a38dSSergiu Cuciurean 		.gain_min = -31750,
75cc74a38dSSergiu Cuciurean 		.gain_max = 0,
76cc74a38dSSergiu Cuciurean 	},
7711ab555aSAlexandru Ardelean };
7811ab555aSAlexandru Ardelean 
ad8366_write(struct iio_dev * indio_dev,unsigned char ch_a,unsigned char ch_b)79e71d42e0SMichael Hennerich static int ad8366_write(struct iio_dev *indio_dev,
80ff6f4629SRoberta Dobrescu 			unsigned char ch_a, unsigned char ch_b)
81e71d42e0SMichael Hennerich {
82e71d42e0SMichael Hennerich 	struct ad8366_state *st = iio_priv(indio_dev);
83e71d42e0SMichael Hennerich 	int ret;
84e71d42e0SMichael Hennerich 
8511ab555aSAlexandru Ardelean 	switch (st->type) {
8611ab555aSAlexandru Ardelean 	case ID_AD8366:
87e71d42e0SMichael Hennerich 		ch_a = bitrev8(ch_a & 0x3F);
88e71d42e0SMichael Hennerich 		ch_b = bitrev8(ch_b & 0x3F);
89e71d42e0SMichael Hennerich 
90e71d42e0SMichael Hennerich 		st->data[0] = ch_b >> 4;
91e71d42e0SMichael Hennerich 		st->data[1] = (ch_b << 4) | (ch_a >> 2);
9211ab555aSAlexandru Ardelean 		break;
93cee211f4SPaul Cercueil 	case ID_ADA4961:
94cee211f4SPaul Cercueil 		st->data[0] = ch_a & 0x1F;
95cee211f4SPaul Cercueil 		break;
96075da9cdSAlexandru Ardelean 	case ID_ADL5240:
97075da9cdSAlexandru Ardelean 		st->data[0] = (ch_a & 0x3F);
98075da9cdSAlexandru Ardelean 		break;
99*247d3b63SKim Seer Paller 	case ID_HMC792:
100cc74a38dSSergiu Cuciurean 	case ID_HMC1119:
101cc74a38dSSergiu Cuciurean 		st->data[0] = ch_a;
102cc74a38dSSergiu Cuciurean 		break;
10311ab555aSAlexandru Ardelean 	}
104e71d42e0SMichael Hennerich 
10511ab555aSAlexandru Ardelean 	ret = spi_write(st->spi, st->data, indio_dev->num_channels);
106e71d42e0SMichael Hennerich 	if (ret < 0)
107e71d42e0SMichael Hennerich 		dev_err(&indio_dev->dev, "write failed (%d)", ret);
108e71d42e0SMichael Hennerich 
109e71d42e0SMichael Hennerich 	return ret;
110e71d42e0SMichael Hennerich }
111e71d42e0SMichael Hennerich 
ad8366_read_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int * val,int * val2,long m)112e71d42e0SMichael Hennerich static int ad8366_read_raw(struct iio_dev *indio_dev,
113e71d42e0SMichael Hennerich 			   struct iio_chan_spec const *chan,
114e71d42e0SMichael Hennerich 			   int *val,
115e71d42e0SMichael Hennerich 			   int *val2,
116e71d42e0SMichael Hennerich 			   long m)
117e71d42e0SMichael Hennerich {
118e71d42e0SMichael Hennerich 	struct ad8366_state *st = iio_priv(indio_dev);
119e71d42e0SMichael Hennerich 	int ret;
12011ab555aSAlexandru Ardelean 	int code, gain = 0;
121e71d42e0SMichael Hennerich 
122dbcf6b5dSAlexandru Ardelean 	mutex_lock(&st->lock);
123e71d42e0SMichael Hennerich 	switch (m) {
124e71d42e0SMichael Hennerich 	case IIO_CHAN_INFO_HARDWAREGAIN:
125e71d42e0SMichael Hennerich 		code = st->ch[chan->channel];
126e71d42e0SMichael Hennerich 
12711ab555aSAlexandru Ardelean 		switch (st->type) {
12811ab555aSAlexandru Ardelean 		case ID_AD8366:
12911ab555aSAlexandru Ardelean 			gain = code * 253 + 4500;
13011ab555aSAlexandru Ardelean 			break;
131cee211f4SPaul Cercueil 		case ID_ADA4961:
132cee211f4SPaul Cercueil 			gain = 15000 - code * 1000;
133cee211f4SPaul Cercueil 			break;
134075da9cdSAlexandru Ardelean 		case ID_ADL5240:
135075da9cdSAlexandru Ardelean 			gain = 20000 - 31500 + code * 500;
136075da9cdSAlexandru Ardelean 			break;
137*247d3b63SKim Seer Paller 		case ID_HMC792:
138*247d3b63SKim Seer Paller 			gain = -1 * code * 500;
139*247d3b63SKim Seer Paller 			break;
140cc74a38dSSergiu Cuciurean 		case ID_HMC1119:
141cc74a38dSSergiu Cuciurean 			gain = -1 * code * 250;
142cc74a38dSSergiu Cuciurean 			break;
14311ab555aSAlexandru Ardelean 		}
14411ab555aSAlexandru Ardelean 
145e71d42e0SMichael Hennerich 		/* Values in dB */
14611ab555aSAlexandru Ardelean 		*val = gain / 1000;
14711ab555aSAlexandru Ardelean 		*val2 = (gain % 1000) * 1000;
148e71d42e0SMichael Hennerich 
149e71d42e0SMichael Hennerich 		ret = IIO_VAL_INT_PLUS_MICRO_DB;
150e71d42e0SMichael Hennerich 		break;
151e71d42e0SMichael Hennerich 	default:
152e71d42e0SMichael Hennerich 		ret = -EINVAL;
153e71d42e0SMichael Hennerich 	}
154dbcf6b5dSAlexandru Ardelean 	mutex_unlock(&st->lock);
155e71d42e0SMichael Hennerich 
156e71d42e0SMichael Hennerich 	return ret;
157e71d42e0SMichael Hennerich };
158e71d42e0SMichael Hennerich 
ad8366_write_raw(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,int val,int val2,long mask)159e71d42e0SMichael Hennerich static int ad8366_write_raw(struct iio_dev *indio_dev,
160e71d42e0SMichael Hennerich 			    struct iio_chan_spec const *chan,
161e71d42e0SMichael Hennerich 			    int val,
162e71d42e0SMichael Hennerich 			    int val2,
163e71d42e0SMichael Hennerich 			    long mask)
164e71d42e0SMichael Hennerich {
165e71d42e0SMichael Hennerich 	struct ad8366_state *st = iio_priv(indio_dev);
16611ab555aSAlexandru Ardelean 	struct ad8366_info *inf = st->info;
16711ab555aSAlexandru Ardelean 	int code = 0, gain;
168e71d42e0SMichael Hennerich 	int ret;
169e71d42e0SMichael Hennerich 
170e71d42e0SMichael Hennerich 	/* Values in dB */
17111ab555aSAlexandru Ardelean 	if (val < 0)
17211ab555aSAlexandru Ardelean 		gain = (val * 1000) - (val2 / 1000);
17311ab555aSAlexandru Ardelean 	else
17411ab555aSAlexandru Ardelean 		gain = (val * 1000) + (val2 / 1000);
175e71d42e0SMichael Hennerich 
17611ab555aSAlexandru Ardelean 	if (gain > inf->gain_max || gain < inf->gain_min)
177e71d42e0SMichael Hennerich 		return -EINVAL;
178e71d42e0SMichael Hennerich 
17911ab555aSAlexandru Ardelean 	switch (st->type) {
18011ab555aSAlexandru Ardelean 	case ID_AD8366:
18111ab555aSAlexandru Ardelean 		code = (gain - 4500) / 253;
18211ab555aSAlexandru Ardelean 		break;
183cee211f4SPaul Cercueil 	case ID_ADA4961:
184cee211f4SPaul Cercueil 		code = (15000 - gain) / 1000;
185cee211f4SPaul Cercueil 		break;
186075da9cdSAlexandru Ardelean 	case ID_ADL5240:
187075da9cdSAlexandru Ardelean 		code = ((gain - 500 - 20000) / 500) & 0x3F;
188075da9cdSAlexandru Ardelean 		break;
189*247d3b63SKim Seer Paller 	case ID_HMC792:
190*247d3b63SKim Seer Paller 		code = (abs(gain) / 500) & 0x3F;
191*247d3b63SKim Seer Paller 		break;
192cc74a38dSSergiu Cuciurean 	case ID_HMC1119:
193cc74a38dSSergiu Cuciurean 		code = (abs(gain) / 250) & 0x7F;
194cc74a38dSSergiu Cuciurean 		break;
19511ab555aSAlexandru Ardelean 	}
196e71d42e0SMichael Hennerich 
197dbcf6b5dSAlexandru Ardelean 	mutex_lock(&st->lock);
198e71d42e0SMichael Hennerich 	switch (mask) {
199e71d42e0SMichael Hennerich 	case IIO_CHAN_INFO_HARDWAREGAIN:
200e71d42e0SMichael Hennerich 		st->ch[chan->channel] = code;
201e71d42e0SMichael Hennerich 		ret = ad8366_write(indio_dev, st->ch[0], st->ch[1]);
202e71d42e0SMichael Hennerich 		break;
203e71d42e0SMichael Hennerich 	default:
204e71d42e0SMichael Hennerich 		ret = -EINVAL;
205e71d42e0SMichael Hennerich 	}
206dbcf6b5dSAlexandru Ardelean 	mutex_unlock(&st->lock);
207e71d42e0SMichael Hennerich 
208e71d42e0SMichael Hennerich 	return ret;
209e71d42e0SMichael Hennerich }
210e71d42e0SMichael Hennerich 
ad8366_write_raw_get_fmt(struct iio_dev * indio_dev,struct iio_chan_spec const * chan,long mask)2110cc97f2eSBeniamin Bia static int ad8366_write_raw_get_fmt(struct iio_dev *indio_dev,
2120cc97f2eSBeniamin Bia 				    struct iio_chan_spec const *chan,
2130cc97f2eSBeniamin Bia 				    long mask)
2140cc97f2eSBeniamin Bia {
2150cc97f2eSBeniamin Bia 	switch (mask) {
2160cc97f2eSBeniamin Bia 	case IIO_CHAN_INFO_HARDWAREGAIN:
2170cc97f2eSBeniamin Bia 		return IIO_VAL_INT_PLUS_MICRO_DB;
2180cc97f2eSBeniamin Bia 	default:
2190cc97f2eSBeniamin Bia 		return -EINVAL;
2200cc97f2eSBeniamin Bia 	}
2210cc97f2eSBeniamin Bia }
2220cc97f2eSBeniamin Bia 
223e71d42e0SMichael Hennerich static const struct iio_info ad8366_info = {
224e71d42e0SMichael Hennerich 	.read_raw = &ad8366_read_raw,
225e71d42e0SMichael Hennerich 	.write_raw = &ad8366_write_raw,
2260cc97f2eSBeniamin Bia 	.write_raw_get_fmt = &ad8366_write_raw_get_fmt,
227e71d42e0SMichael Hennerich };
228e71d42e0SMichael Hennerich 
229e71d42e0SMichael Hennerich #define AD8366_CHAN(_channel) {				\
230e71d42e0SMichael Hennerich 	.type = IIO_VOLTAGE,				\
231e71d42e0SMichael Hennerich 	.output = 1,					\
232e71d42e0SMichael Hennerich 	.indexed = 1,					\
233e71d42e0SMichael Hennerich 	.channel = _channel,				\
234b34ec6f3SJonathan Cameron 	.info_mask_separate = BIT(IIO_CHAN_INFO_HARDWAREGAIN),\
235e71d42e0SMichael Hennerich }
236e71d42e0SMichael Hennerich 
237e71d42e0SMichael Hennerich static const struct iio_chan_spec ad8366_channels[] = {
238e71d42e0SMichael Hennerich 	AD8366_CHAN(0),
239e71d42e0SMichael Hennerich 	AD8366_CHAN(1),
240e71d42e0SMichael Hennerich };
241e71d42e0SMichael Hennerich 
242cee211f4SPaul Cercueil static const struct iio_chan_spec ada4961_channels[] = {
243cee211f4SPaul Cercueil 	AD8366_CHAN(0),
244cee211f4SPaul Cercueil };
245cee211f4SPaul Cercueil 
ad8366_probe(struct spi_device * spi)246fc52692cSGreg Kroah-Hartman static int ad8366_probe(struct spi_device *spi)
247e71d42e0SMichael Hennerich {
248e71d42e0SMichael Hennerich 	struct iio_dev *indio_dev;
249e71d42e0SMichael Hennerich 	struct ad8366_state *st;
250e71d42e0SMichael Hennerich 	int ret;
251e71d42e0SMichael Hennerich 
25236db8c72SSachin Kamat 	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
253e71d42e0SMichael Hennerich 	if (indio_dev == NULL)
254e71d42e0SMichael Hennerich 		return -ENOMEM;
255e71d42e0SMichael Hennerich 
256e71d42e0SMichael Hennerich 	st = iio_priv(indio_dev);
257e71d42e0SMichael Hennerich 
25836db8c72SSachin Kamat 	st->reg = devm_regulator_get(&spi->dev, "vcc");
259e71d42e0SMichael Hennerich 	if (!IS_ERR(st->reg)) {
260e71d42e0SMichael Hennerich 		ret = regulator_enable(st->reg);
261e71d42e0SMichael Hennerich 		if (ret)
26236db8c72SSachin Kamat 			return ret;
263e71d42e0SMichael Hennerich 	}
264e71d42e0SMichael Hennerich 
265e71d42e0SMichael Hennerich 	spi_set_drvdata(spi, indio_dev);
266dbcf6b5dSAlexandru Ardelean 	mutex_init(&st->lock);
267e71d42e0SMichael Hennerich 	st->spi = spi;
26811ab555aSAlexandru Ardelean 	st->type = spi_get_device_id(spi)->driver_data;
269e71d42e0SMichael Hennerich 
27011ab555aSAlexandru Ardelean 	switch (st->type) {
27111ab555aSAlexandru Ardelean 	case ID_AD8366:
27211ab555aSAlexandru Ardelean 		indio_dev->channels = ad8366_channels;
27311ab555aSAlexandru Ardelean 		indio_dev->num_channels = ARRAY_SIZE(ad8366_channels);
27411ab555aSAlexandru Ardelean 		break;
275cee211f4SPaul Cercueil 	case ID_ADA4961:
276075da9cdSAlexandru Ardelean 	case ID_ADL5240:
277*247d3b63SKim Seer Paller 	case ID_HMC792:
278cc74a38dSSergiu Cuciurean 	case ID_HMC1119:
2799ca39411SChuhong Yuan 		st->reset_gpio = devm_gpiod_get_optional(&spi->dev, "reset", GPIOD_OUT_HIGH);
2809ca39411SChuhong Yuan 		if (IS_ERR(st->reset_gpio)) {
2819ca39411SChuhong Yuan 			ret = PTR_ERR(st->reset_gpio);
2829ca39411SChuhong Yuan 			goto error_disable_reg;
2839ca39411SChuhong Yuan 		}
284cee211f4SPaul Cercueil 		indio_dev->channels = ada4961_channels;
285cee211f4SPaul Cercueil 		indio_dev->num_channels = ARRAY_SIZE(ada4961_channels);
286cee211f4SPaul Cercueil 		break;
28711ab555aSAlexandru Ardelean 	default:
28811ab555aSAlexandru Ardelean 		dev_err(&spi->dev, "Invalid device ID\n");
28911ab555aSAlexandru Ardelean 		ret = -EINVAL;
29011ab555aSAlexandru Ardelean 		goto error_disable_reg;
29111ab555aSAlexandru Ardelean 	}
29211ab555aSAlexandru Ardelean 
29311ab555aSAlexandru Ardelean 	st->info = &ad8366_infos[st->type];
294e71d42e0SMichael Hennerich 	indio_dev->name = spi_get_device_id(spi)->name;
295e71d42e0SMichael Hennerich 	indio_dev->info = &ad8366_info;
296e71d42e0SMichael Hennerich 	indio_dev->modes = INDIO_DIRECT_MODE;
297e71d42e0SMichael Hennerich 
2982636d005SAlexandru Ardelean 	ret = ad8366_write(indio_dev, 0, 0);
2992636d005SAlexandru Ardelean 	if (ret < 0)
3002636d005SAlexandru Ardelean 		goto error_disable_reg;
3012636d005SAlexandru Ardelean 
302e71d42e0SMichael Hennerich 	ret = iio_device_register(indio_dev);
303e71d42e0SMichael Hennerich 	if (ret)
304e71d42e0SMichael Hennerich 		goto error_disable_reg;
305e71d42e0SMichael Hennerich 
306e71d42e0SMichael Hennerich 	return 0;
307e71d42e0SMichael Hennerich 
308e71d42e0SMichael Hennerich error_disable_reg:
309e71d42e0SMichael Hennerich 	if (!IS_ERR(st->reg))
310e71d42e0SMichael Hennerich 		regulator_disable(st->reg);
311e71d42e0SMichael Hennerich 
312e71d42e0SMichael Hennerich 	return ret;
313e71d42e0SMichael Hennerich }
314e71d42e0SMichael Hennerich 
ad8366_remove(struct spi_device * spi)315a0386bbaSUwe Kleine-König static void ad8366_remove(struct spi_device *spi)
316e71d42e0SMichael Hennerich {
317e71d42e0SMichael Hennerich 	struct iio_dev *indio_dev = spi_get_drvdata(spi);
318e71d42e0SMichael Hennerich 	struct ad8366_state *st = iio_priv(indio_dev);
319e71d42e0SMichael Hennerich 	struct regulator *reg = st->reg;
320e71d42e0SMichael Hennerich 
321e71d42e0SMichael Hennerich 	iio_device_unregister(indio_dev);
322e71d42e0SMichael Hennerich 
323d3789c3eSSachin Kamat 	if (!IS_ERR(reg))
324e71d42e0SMichael Hennerich 		regulator_disable(reg);
325e71d42e0SMichael Hennerich }
326e71d42e0SMichael Hennerich 
327e71d42e0SMichael Hennerich static const struct spi_device_id ad8366_id[] = {
32811ab555aSAlexandru Ardelean 	{"ad8366",  ID_AD8366},
329cee211f4SPaul Cercueil 	{"ada4961", ID_ADA4961},
330075da9cdSAlexandru Ardelean 	{"adl5240", ID_ADL5240},
331*247d3b63SKim Seer Paller 	{"hmc792a", ID_HMC792},
332cc74a38dSSergiu Cuciurean 	{"hmc1119", ID_HMC1119},
333e71d42e0SMichael Hennerich 	{}
334e71d42e0SMichael Hennerich };
335ed199a11SJavier Martinez Canillas MODULE_DEVICE_TABLE(spi, ad8366_id);
336e71d42e0SMichael Hennerich 
337e71d42e0SMichael Hennerich static struct spi_driver ad8366_driver = {
338e71d42e0SMichael Hennerich 	.driver = {
339e71d42e0SMichael Hennerich 		.name	= KBUILD_MODNAME,
340e71d42e0SMichael Hennerich 	},
341e71d42e0SMichael Hennerich 	.probe		= ad8366_probe,
342fc52692cSGreg Kroah-Hartman 	.remove		= ad8366_remove,
343e71d42e0SMichael Hennerich 	.id_table	= ad8366_id,
344e71d42e0SMichael Hennerich };
345e71d42e0SMichael Hennerich 
346e71d42e0SMichael Hennerich module_spi_driver(ad8366_driver);
347e71d42e0SMichael Hennerich 
3489920ed25SMichael Hennerich MODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
349cee211f4SPaul Cercueil MODULE_DESCRIPTION("Analog Devices AD8366 and similar Gain Amplifiers");
350e71d42e0SMichael Hennerich MODULE_LICENSE("GPL v2");
351