ad7266.c revision fc52692c49969ec72595766929b9f54ac402da34
18ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen/*
28ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen * AD7266/65 SPI ADC driver
38ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen *
48ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen * Copyright 2012 Analog Devices Inc.
58ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen *
68ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen * Licensed under the GPL-2.
78ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen */
88ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
98ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/device.h>
108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/kernel.h>
118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/slab.h>
128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/spi/spi.h>
138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/regulator/consumer.h>
148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/err.h>
158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/gpio.h>
168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/module.h>
178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/interrupt.h>
198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/iio/iio.h>
218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/iio/buffer.h>
228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/iio/trigger_consumer.h>
238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/iio/triggered_buffer.h>
248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#include <linux/platform_data/ad7266.h>
268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstruct ad7266_state {
288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct spi_device	*spi;
298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct regulator	*reg;
308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned long		vref_uv;
318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct spi_transfer	single_xfer[3];
338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct spi_message	single_msg;
348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	enum ad7266_range	range;
368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	enum ad7266_mode	mode;
378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	bool			fixed_addr;
388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct gpio		gpios[3];
398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/*
418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	 * DMA (thus cache coherency maintenance) requires the
428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	 * transfer buffers to live in their own cache lines.
438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	 * The buffer needs to be large enough to hold two samples (4 bytes) and
448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	 * the naturally aligned timestamp (8 bytes).
458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	 */
468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	uint8_t data[ALIGN(4, sizeof(s64)) + sizeof(s64)] ____cacheline_aligned;
478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_wakeup(struct ad7266_state *st)
508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* Any read with >= 2 bytes will wake the device */
528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return spi_read(st->spi, st->data, 2);
538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_powerdown(struct ad7266_state *st)
568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* Any read with < 2 bytes will powerdown the device */
588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return spi_read(st->spi, st->data, 1);
598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_preenable(struct iio_dev *indio_dev)
628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = ad7266_wakeup(st);
678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return ret;
698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_sw_buffer_preenable(indio_dev);
718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ad7266_powerdown(st);
738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_postdisable(struct iio_dev *indio_dev)
788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ad7266_powerdown(st);
818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.preenable = &ad7266_preenable,
858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.postenable = &iio_triggered_buffer_postenable,
868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.predisable = &iio_triggered_buffer_predisable,
878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.postdisable = &ad7266_postdisable,
888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic irqreturn_t ad7266_trigger_handler(int irq, void *p)
918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_poll_func *pf = p;
938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev = pf->indio_dev;
948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = spi_read(st->spi, st->data, 4);
988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret == 0) {
998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (indio_dev->scan_timestamp)
1008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			((s64 *)st->data)[1] = pf->timestamp;
10184b36ce5f79c01f792c623f14e92ed86cdccb42fJonathan Cameron		iio_push_to_buffers(indio_dev, (u8 *)st->data);
1028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_trigger_notify_done(indio_dev->trig);
1058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return IRQ_HANDLED;
1078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
1108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int i;
1128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (st->fixed_addr)
1148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return;
1158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	switch (st->mode) {
1178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_SINGLE_ENDED:
1188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr >>= 1;
1198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_PSEUDO_DIFF:
1218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr |= 1;
1228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_DIFF:
1248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr &= ~1;
1258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	for (i = 0; i < 3; ++i)
1298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i)));
1308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_update_scan_mode(struct iio_dev *indio_dev,
1338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const unsigned long *scan_mask)
1348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
1368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength);
1378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_select_input(st, nr);
1398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
1418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_read_single(struct ad7266_state *st, int *val,
1448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int address)
1458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
1478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_select_input(st, address);
1498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = spi_sync(st->spi, &st->single_msg);
1518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	*val = be16_to_cpu(st->data[address % 2]);
1528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
1548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_read_raw(struct iio_dev *indio_dev,
1578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_chan_spec const *chan, int *val, int *val2, long m)
1588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
1608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned long scale_uv;
1618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
1628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	switch (m) {
1648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_RAW:
1658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (iio_buffer_enabled(indio_dev))
1668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			return -EBUSY;
1678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ret = ad7266_read_single(st, val, chan->address);
1698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (ret)
1708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			return ret;
1718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val = (*val >> 2) & 0xfff;
1738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (chan->scan_type.sign == 's')
1748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = sign_extend32(*val, 11);
1758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT;
1778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_SCALE:
1788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		scale_uv = (st->vref_uv * 100);
1798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->mode == AD7266_MODE_DIFF)
1808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			scale_uv *= 2;
1818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->range == AD7266_RANGE_2VREF)
1828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			scale_uv *= 2;
1838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		scale_uv >>= chan->scan_type.realbits;
1858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val =  scale_uv / 100000;
1868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val2 = (scale_uv % 100000) * 10;
1878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT_PLUS_MICRO;
1888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_OFFSET:
1898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->range == AD7266_RANGE_2VREF &&
1908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			st->mode != AD7266_MODE_DIFF)
1918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = 2048;
1928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		else
1938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = 0;
1948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT;
1958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return -EINVAL;
1978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN(_chan, _sign) {			\
2008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.type = IIO_VOLTAGE,				\
2018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.indexed = 1,					\
2028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel = (_chan),				\
2038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.address = (_chan),				\
2048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT	\
2058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		| IIO_CHAN_INFO_SCALE_SHARED_BIT	\
2068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		| IIO_CHAN_INFO_OFFSET_SHARED_BIT,	\
2078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_index = (_chan),				\
2088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_type = {					\
2098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.sign = (_sign),			\
2108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.realbits = 12,				\
2118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.storagebits = 16,			\
2128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.shift = 2,				\
2138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.endianness = IIO_BE,			\
2148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},						\
2158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \
2188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_##_name[] = { \
2198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(0, (_sign)), \
2208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(1, (_sign)), \
2218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(2, (_sign)), \
2228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(3, (_sign)), \
2238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(4, (_sign)), \
2248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(5, (_sign)), \
2258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(6, (_sign)), \
2268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(7, (_sign)), \
2278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(8, (_sign)), \
2288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(9, (_sign)), \
2298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(10, (_sign)), \
2308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(11, (_sign)), \
2318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(13), \
2328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \
2358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \
2368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(0, (_sign)), \
2378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(1, (_sign)), \
2388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(2), \
2398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u');
2428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's');
2438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u');
2448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
2458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN_DIFF(_chan, _sign) {			\
2478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.type = IIO_VOLTAGE,				\
2488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.indexed = 1,					\
2498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel = (_chan) * 2,				\
2508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel2 = (_chan) * 2 + 1,			\
2518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.address = (_chan),				\
2528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.info_mask = IIO_CHAN_INFO_RAW_SEPARATE_BIT	\
2538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		| IIO_CHAN_INFO_SCALE_SHARED_BIT	\
2548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		| IIO_CHAN_INFO_OFFSET_SHARED_BIT,	\
2558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_index = (_chan),				\
2568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_type = {					\
2578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.sign = _sign,			\
2588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.realbits = 12,				\
2598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.storagebits = 16,			\
2608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.shift = 2,				\
2618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.endianness = IIO_BE,			\
2628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},						\
2638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.differential = 1,				\
2648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \
2678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_diff_##_name[] = { \
2688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(0, (_sign)), \
2698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(1, (_sign)), \
2708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(2, (_sign)), \
2718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(3, (_sign)), \
2728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(4, (_sign)), \
2738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(5, (_sign)), \
2748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(6), \
2758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS(s, 's');
2788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS(u, 'u');
2798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \
2818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \
2828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(0, (_sign)), \
2838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(1, (_sign)), \
2848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(2), \
2858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's');
2888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u');
2898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct iio_info ad7266_info = {
2918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.read_raw = &ad7266_read_raw,
2928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.update_scan_mode = &ad7266_update_scan_mode,
2938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.driver_module = THIS_MODULE,
2948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
2958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic unsigned long ad7266_available_scan_masks[] = {
2978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
2988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x00c,
2998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x030,
3008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x0c0,
3018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x300,
3028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0xc00,
3038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic unsigned long ad7266_available_scan_masks_diff[] = {
3078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
3088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x00c,
3098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x030,
3108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic unsigned long ad7266_available_scan_masks_fixed[] = {
3148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
3158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstruct ad7266_chan_info {
3198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const struct iio_chan_spec *channels;
3208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int num_channels;
3218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned long *scan_masks;
3228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
3258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	(((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0))
3268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct ad7266_chan_info ad7266_chan_infos[] = {
3288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 0, 0)] = {
3298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_u,
3308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_u),
3318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks,
3328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 0, 1)] = {
3348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_u_fixed,
3358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_u_fixed),
3368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 1, 0)] = {
3398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_s,
3408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_s),
3418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks,
3428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 1, 1)] = {
3448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_s_fixed,
3458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_s_fixed),
3468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 0, 0)] = {
3498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_u,
3508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_u),
3518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_diff,
3528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 0, 1)] = {
3548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_fixed_u,
3558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u),
3568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 1, 0)] = {
3598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_s,
3608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_s),
3618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_diff,
3628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 1, 1)] = {
3648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_fixed_s,
3658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s),
3668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
370fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic void ad7266_init_channels(struct iio_dev *indio_dev)
3718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
3728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
3738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	bool is_differential, is_signed;
3748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const struct ad7266_chan_info *chan_info;
3758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int i;
3768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	is_differential = st->mode != AD7266_MODE_SINGLE_ENDED;
3788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	is_signed = (st->range == AD7266_RANGE_2VREF) |
3798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		    (st->mode == AD7266_MODE_DIFF);
3808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr);
3828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	chan_info = &ad7266_chan_infos[i];
3838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->channels = chan_info->channels;
3858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->num_channels = chan_info->num_channels;
3868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->available_scan_masks = chan_info->scan_masks;
3878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->masklength = chan_info->num_channels - 1;
3888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
3898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const char * const ad7266_gpio_labels[] = {
3918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	"AD0", "AD1", "AD2",
3928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
394fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic int ad7266_probe(struct spi_device *spi)
3958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
3968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_platform_data *pdata = spi->dev.platform_data;
3978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev;
3988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st;
3998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int i;
4008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
4018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev = iio_device_alloc(sizeof(*st));
4038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (indio_dev == NULL)
4048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return -ENOMEM;
4058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st = iio_priv(indio_dev);
4078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->reg = regulator_get(&spi->dev, "vref");
4098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg)) {
4108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ret = regulator_enable(st->reg);
4118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (ret)
4128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			goto error_put_reg;
4138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->vref_uv = regulator_get_voltage(st->reg);
4158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	} else {
4168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		/* Use internal reference */
4178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->vref_uv = 2500000;
4188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
4198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (pdata) {
4218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->fixed_addr = pdata->fixed_addr;
4228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->mode = pdata->mode;
4238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->range = pdata->range;
4248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (!st->fixed_addr) {
4268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
4278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].gpio = pdata->addr_gpios[i];
4288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].flags = GPIOF_OUT_INIT_LOW;
4298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].label = ad7266_gpio_labels[i];
4308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			}
4318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			ret = gpio_request_array(st->gpios,
4328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				ARRAY_SIZE(st->gpios));
4338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			if (ret)
4348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				goto error_disable_reg;
4358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		}
4368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	} else {
4378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->fixed_addr = true;
4388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->range = AD7266_RANGE_VREF;
4398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->mode = AD7266_MODE_DIFF;
4408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
4418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_set_drvdata(spi, indio_dev);
4438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->spi = spi;
4448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->dev.parent = &spi->dev;
4468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->name = spi_get_device_id(spi)->name;
4478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->modes = INDIO_DIRECT_MODE;
4488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->info = &ad7266_info;
4498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_init_channels(indio_dev);
4518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* wakeup */
4538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].rx_buf = &st->data;
4548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].len = 2;
4558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].cs_change = 1;
4568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* conversion */
4578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].rx_buf = &st->data;
4588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].len = 4;
4598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].cs_change = 1;
4608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* powerdown */
4618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[2].tx_buf = &st->data;
4628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[2].len = 1;
4638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_init(&st->single_msg);
4658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[0], &st->single_msg);
4668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
4678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
4688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
4708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
4718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
4728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		goto error_free_gpios;
4738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_device_register(indio_dev);
4758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
4768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		goto error_buffer_cleanup;
4778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
4798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_buffer_cleanup:
4818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_triggered_buffer_cleanup(indio_dev);
4828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_free_gpios:
4838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!st->fixed_addr)
4848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
4858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_disable_reg:
4868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg))
4878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_disable(st->reg);
4888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_put_reg:
4898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg))
4908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_put(st->reg);
4918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_device_free(indio_dev);
4938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
4958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
4968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
497fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic int ad7266_remove(struct spi_device *spi)
4988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
4998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev = spi_get_drvdata(spi);
5008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
5018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_device_unregister(indio_dev);
5038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_triggered_buffer_cleanup(indio_dev);
5048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!st->fixed_addr)
5058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
5068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg)) {
5078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_disable(st->reg);
5088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_put(st->reg);
5098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
5108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_device_free(indio_dev);
5118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
5138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
5148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct spi_device_id ad7266_id[] = {
5168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{"ad7265", 0},
5178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{"ad7266", 0},
5188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{ }
5198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
5208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_DEVICE_TABLE(spi, ad7266_id);
5218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic struct spi_driver ad7266_driver = {
5238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.driver = {
5248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.name	= "ad7266",
5258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.owner	= THIS_MODULE,
5268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
5278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.probe		= ad7266_probe,
528fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartman	.remove		= ad7266_remove,
5298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.id_table	= ad7266_id,
5308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
5318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenmodule_spi_driver(ad7266_driver);
5328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
5348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_DESCRIPTION("Analog Devices AD7266/65 ADC");
5358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_LICENSE("GPL v2");
536