ad7266.c revision fce8abfda40a764f4662ee354c1646ec78061371
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) {
99fce8abfda40a764f4662ee354c1646ec78061371Lars-Peter Clausen		iio_push_to_buffers_with_timestamp(indio_dev, st->data,
100fce8abfda40a764f4662ee354c1646ec78061371Lars-Peter Clausen			    pf->timestamp);
1018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_trigger_notify_done(indio_dev->trig);
1048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return IRQ_HANDLED;
1068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
1098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int i;
1118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (st->fixed_addr)
1138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return;
1148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	switch (st->mode) {
1168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_SINGLE_ENDED:
1178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr >>= 1;
1188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_PSEUDO_DIFF:
1208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr |= 1;
1218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_DIFF:
1238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr &= ~1;
1248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	for (i = 0; i < 3; ++i)
1288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i)));
1298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_update_scan_mode(struct iio_dev *indio_dev,
1328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const unsigned long *scan_mask)
1338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
1358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength);
1368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_select_input(st, nr);
1388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
1408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_read_single(struct ad7266_state *st, int *val,
1438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int address)
1448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
1468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_select_input(st, address);
1488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = spi_sync(st->spi, &st->single_msg);
1508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	*val = be16_to_cpu(st->data[address % 2]);
1518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
1538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_read_raw(struct iio_dev *indio_dev,
1568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_chan_spec const *chan, int *val, int *val2, long m)
1578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
1598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned long scale_uv;
1608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
1618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	switch (m) {
1638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_RAW:
1648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (iio_buffer_enabled(indio_dev))
1658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			return -EBUSY;
1668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ret = ad7266_read_single(st, val, chan->address);
1688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (ret)
1698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			return ret;
1708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val = (*val >> 2) & 0xfff;
1728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (chan->scan_type.sign == 's')
1738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = sign_extend32(*val, 11);
1748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT;
1768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_SCALE:
1778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		scale_uv = (st->vref_uv * 100);
1788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->mode == AD7266_MODE_DIFF)
1798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			scale_uv *= 2;
1808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->range == AD7266_RANGE_2VREF)
1818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			scale_uv *= 2;
1828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		scale_uv >>= chan->scan_type.realbits;
1848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val =  scale_uv / 100000;
1858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val2 = (scale_uv % 100000) * 10;
1868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT_PLUS_MICRO;
1878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_OFFSET:
1888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->range == AD7266_RANGE_2VREF &&
1898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			st->mode != AD7266_MODE_DIFF)
1908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = 2048;
1918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		else
1928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = 0;
1938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT;
1948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return -EINVAL;
1968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN(_chan, _sign) {			\
1998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.type = IIO_VOLTAGE,				\
2008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.indexed = 1,					\
2018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel = (_chan),				\
2028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.address = (_chan),				\
2033234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
2043234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
2053234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron		| BIT(IIO_CHAN_INFO_OFFSET),			\
2068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_index = (_chan),				\
2078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_type = {					\
2088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.sign = (_sign),			\
2098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.realbits = 12,				\
2108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.storagebits = 16,			\
2118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.shift = 2,				\
2128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.endianness = IIO_BE,			\
2138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},						\
2148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \
2178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_##_name[] = { \
2188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(0, (_sign)), \
2198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(1, (_sign)), \
2208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(2, (_sign)), \
2218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(3, (_sign)), \
2228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(4, (_sign)), \
2238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(5, (_sign)), \
2248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(6, (_sign)), \
2258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(7, (_sign)), \
2268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(8, (_sign)), \
2278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(9, (_sign)), \
2288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(10, (_sign)), \
2298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(11, (_sign)), \
2308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(13), \
2318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \
2348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \
2358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(0, (_sign)), \
2368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(1, (_sign)), \
2378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(2), \
2388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u');
2418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's');
2428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u');
2438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
2448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN_DIFF(_chan, _sign) {			\
2468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.type = IIO_VOLTAGE,				\
2478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.indexed = 1,					\
2488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel = (_chan) * 2,				\
2498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel2 = (_chan) * 2 + 1,			\
2508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.address = (_chan),				\
2513234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
2523234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
2533234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron		| BIT(IIO_CHAN_INFO_OFFSET),			\
2548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_index = (_chan),				\
2558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_type = {					\
2568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.sign = _sign,			\
2578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.realbits = 12,				\
2588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.storagebits = 16,			\
2598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.shift = 2,				\
2608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.endianness = IIO_BE,			\
2618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},						\
2628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.differential = 1,				\
2638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \
2668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_diff_##_name[] = { \
2678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(0, (_sign)), \
2688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(1, (_sign)), \
2698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(2, (_sign)), \
2708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(3, (_sign)), \
2718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(4, (_sign)), \
2728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(5, (_sign)), \
2738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(6), \
2748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS(s, 's');
2778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS(u, 'u');
2788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \
2808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \
2818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(0, (_sign)), \
2828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(1, (_sign)), \
2838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(2), \
2848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's');
2878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u');
2888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct iio_info ad7266_info = {
2908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.read_raw = &ad7266_read_raw,
2918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.update_scan_mode = &ad7266_update_scan_mode,
2928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.driver_module = THIS_MODULE,
2938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
2948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2952bdb3afcecff232b8670648755a222494d00981dPeter Meerwaldstatic const unsigned long ad7266_available_scan_masks[] = {
2968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
2978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x00c,
2988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x030,
2998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x0c0,
3008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x300,
3018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0xc00,
3028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3052bdb3afcecff232b8670648755a222494d00981dPeter Meerwaldstatic const unsigned long ad7266_available_scan_masks_diff[] = {
3068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
3078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x00c,
3088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x030,
3098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3122bdb3afcecff232b8670648755a222494d00981dPeter Meerwaldstatic const unsigned long ad7266_available_scan_masks_fixed[] = {
3138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
3148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstruct ad7266_chan_info {
3188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const struct iio_chan_spec *channels;
3198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int num_channels;
3202bdb3afcecff232b8670648755a222494d00981dPeter Meerwald	const unsigned long *scan_masks;
3218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
3248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	(((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0))
3258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct ad7266_chan_info ad7266_chan_infos[] = {
3278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 0, 0)] = {
3288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_u,
3298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_u),
3308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks,
3318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 0, 1)] = {
3338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_u_fixed,
3348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_u_fixed),
3358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 1, 0)] = {
3388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_s,
3398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_s),
3408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks,
3418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 1, 1)] = {
3438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_s_fixed,
3448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_s_fixed),
3458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 0, 0)] = {
3488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_u,
3498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_u),
3508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_diff,
3518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 0, 1)] = {
3538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_fixed_u,
3548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u),
3558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 1, 0)] = {
3588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_s,
3598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_s),
3608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_diff,
3618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 1, 1)] = {
3638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_fixed_s,
3648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s),
3658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
369fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic void ad7266_init_channels(struct iio_dev *indio_dev)
3708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
3718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
3728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	bool is_differential, is_signed;
3738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const struct ad7266_chan_info *chan_info;
3748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int i;
3758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	is_differential = st->mode != AD7266_MODE_SINGLE_ENDED;
3778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	is_signed = (st->range == AD7266_RANGE_2VREF) |
3788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		    (st->mode == AD7266_MODE_DIFF);
3798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr);
3818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	chan_info = &ad7266_chan_infos[i];
3828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->channels = chan_info->channels;
3848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->num_channels = chan_info->num_channels;
3858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->available_scan_masks = chan_info->scan_masks;
3868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->masklength = chan_info->num_channels - 1;
3878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
3888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const char * const ad7266_gpio_labels[] = {
3908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	"AD0", "AD1", "AD2",
3918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
393fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic int ad7266_probe(struct spi_device *spi)
3948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
3958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_platform_data *pdata = spi->dev.platform_data;
3968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev;
3978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st;
3988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int i;
3998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
4008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
401ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
4028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (indio_dev == NULL)
4038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return -ENOMEM;
4048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st = iio_priv(indio_dev);
4068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
407ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat	st->reg = devm_regulator_get(&spi->dev, "vref");
4088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg)) {
4098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ret = regulator_enable(st->reg);
4108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (ret)
411ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat			return ret;
4128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
41336ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin		ret = regulator_get_voltage(st->reg);
41436ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin		if (ret < 0)
41536ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin			goto error_disable_reg;
41636ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin
41736ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin		st->vref_uv = ret;
4188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	} else {
4198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		/* Use internal reference */
4208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->vref_uv = 2500000;
4218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
4228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (pdata) {
4248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->fixed_addr = pdata->fixed_addr;
4258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->mode = pdata->mode;
4268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->range = pdata->range;
4278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (!st->fixed_addr) {
4298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
4308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].gpio = pdata->addr_gpios[i];
4318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].flags = GPIOF_OUT_INIT_LOW;
4328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].label = ad7266_gpio_labels[i];
4338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			}
4348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			ret = gpio_request_array(st->gpios,
4358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				ARRAY_SIZE(st->gpios));
4368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			if (ret)
4378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				goto error_disable_reg;
4388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		}
4398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	} else {
4408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->fixed_addr = true;
4418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->range = AD7266_RANGE_VREF;
4428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->mode = AD7266_MODE_DIFF;
4438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
4448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_set_drvdata(spi, indio_dev);
4468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->spi = spi;
4478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->dev.parent = &spi->dev;
4498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->name = spi_get_device_id(spi)->name;
4508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->modes = INDIO_DIRECT_MODE;
4518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->info = &ad7266_info;
4528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_init_channels(indio_dev);
4548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* wakeup */
4568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].rx_buf = &st->data;
4578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].len = 2;
4588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].cs_change = 1;
4598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* conversion */
4608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].rx_buf = &st->data;
4618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].len = 4;
4628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].cs_change = 1;
4638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* powerdown */
4648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[2].tx_buf = &st->data;
4658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[2].len = 1;
4668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_init(&st->single_msg);
4688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[0], &st->single_msg);
4698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
4708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
4718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
4738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
4748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
4758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		goto error_free_gpios;
4768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_device_register(indio_dev);
4788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
4798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		goto error_buffer_cleanup;
4808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
4828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_buffer_cleanup:
4848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_triggered_buffer_cleanup(indio_dev);
4858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_free_gpios:
4868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!st->fixed_addr)
4878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
4888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_disable_reg:
4898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg))
4908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_disable(st->reg);
4918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
4938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
4948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
495fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic int ad7266_remove(struct spi_device *spi)
4968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
4978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev = spi_get_drvdata(spi);
4988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
4998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_device_unregister(indio_dev);
5018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_triggered_buffer_cleanup(indio_dev);
5028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!st->fixed_addr)
5038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
504ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat	if (!IS_ERR_OR_NULL(st->reg))
5058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_disable(st->reg);
5068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
5088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
5098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct spi_device_id ad7266_id[] = {
5118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{"ad7265", 0},
5128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{"ad7266", 0},
5138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{ }
5148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
5158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_DEVICE_TABLE(spi, ad7266_id);
5168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic struct spi_driver ad7266_driver = {
5188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.driver = {
5198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.name	= "ad7266",
5208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.owner	= THIS_MODULE,
5218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
5228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.probe		= ad7266_probe,
523fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartman	.remove		= ad7266_remove,
5248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.id_table	= ad7266_id,
5258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
5268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenmodule_spi_driver(ad7266_driver);
5278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
5298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_DESCRIPTION("Analog Devices AD7266/65 ADC");
5308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_LICENSE("GPL v2");
531