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;
302ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen	unsigned long		vref_mv;
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	 */
4654e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	struct {
4754e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen		__be16 sample[2];
4854e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen		s64 timestamp;
4954e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	} data ____cacheline_aligned;
508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_wakeup(struct ad7266_state *st)
538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* Any read with >= 2 bytes will wake the device */
5554e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	return spi_read(st->spi, &st->data.sample[0], 2);
568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_powerdown(struct ad7266_state *st)
598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* Any read with < 2 bytes will powerdown the device */
6154e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	return spi_read(st->spi, &st->data.sample[0], 1);
628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_preenable(struct iio_dev *indio_dev)
658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
6706e1b542bb06a84bb536d9865c6547422cc240b5Lars-Peter Clausen	return ad7266_wakeup(st);
688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_postdisable(struct iio_dev *indio_dev)
718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ad7266_powerdown(st);
748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct iio_buffer_setup_ops iio_triggered_buffer_setup_ops = {
778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.preenable = &ad7266_preenable,
788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.postenable = &iio_triggered_buffer_postenable,
798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.predisable = &iio_triggered_buffer_predisable,
808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.postdisable = &ad7266_postdisable,
818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic irqreturn_t ad7266_trigger_handler(int irq, void *p)
848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_poll_func *pf = p;
868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev = pf->indio_dev;
878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
9054e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	ret = spi_read(st->spi, st->data.sample, 4);
918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret == 0) {
9254e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen		iio_push_to_buffers_with_timestamp(indio_dev, &st->data,
93fce8abfda40a764f4662ee354c1646ec78061371Lars-Peter Clausen			    pf->timestamp);
948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_trigger_notify_done(indio_dev->trig);
978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return IRQ_HANDLED;
998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic void ad7266_select_input(struct ad7266_state *st, unsigned int nr)
1028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int i;
1048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (st->fixed_addr)
1068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return;
1078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	switch (st->mode) {
1098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_SINGLE_ENDED:
1108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr >>= 1;
1118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_PSEUDO_DIFF:
1138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr |= 1;
1148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case AD7266_MODE_DIFF:
1168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		nr &= ~1;
1178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		break;
1188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	for (i = 0; i < 3; ++i)
1218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_set_value(st->gpios[i].gpio, (bool)(nr & BIT(i)));
1228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_update_scan_mode(struct iio_dev *indio_dev,
1258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const unsigned long *scan_mask)
1268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
1288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int nr = find_first_bit(scan_mask, indio_dev->masklength);
1298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_select_input(st, nr);
1318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
1338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_read_single(struct ad7266_state *st, int *val,
1368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int address)
1378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
1398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_select_input(st, address);
1418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = spi_sync(st->spi, &st->single_msg);
14354e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	*val = be16_to_cpu(st->data.sample[address % 2]);
1448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
1468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic int ad7266_read_raw(struct iio_dev *indio_dev,
1498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_chan_spec const *chan, int *val, int *val2, long m)
1508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
1518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
1522ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen	unsigned long scale_mv;
1538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
1548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	switch (m) {
1568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_RAW:
1578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (iio_buffer_enabled(indio_dev))
1588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			return -EBUSY;
1598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ret = ad7266_read_single(st, val, chan->address);
1618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (ret)
1628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			return ret;
1638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		*val = (*val >> 2) & 0xfff;
1658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (chan->scan_type.sign == 's')
1668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = sign_extend32(*val, 11);
1678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT;
1698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_SCALE:
1702ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen		scale_mv = st->vref_mv;
1718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->mode == AD7266_MODE_DIFF)
1722ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen			scale_mv *= 2;
1738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->range == AD7266_RANGE_2VREF)
1742ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen			scale_mv *= 2;
1758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1762ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen		*val = scale_mv;
1772ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen		*val2 = chan->scan_type.realbits;
1782ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen		return IIO_VAL_FRACTIONAL_LOG2;
1798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	case IIO_CHAN_INFO_OFFSET:
1808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (st->range == AD7266_RANGE_2VREF &&
1818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			st->mode != AD7266_MODE_DIFF)
1828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = 2048;
1838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		else
1848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			*val = 0;
1858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return IIO_VAL_INT;
1868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
1878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return -EINVAL;
1888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
1898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
1908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN(_chan, _sign) {			\
1918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.type = IIO_VOLTAGE,				\
1928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.indexed = 1,					\
1938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel = (_chan),				\
1948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.address = (_chan),				\
1953234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
1963234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
1973234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron		| BIT(IIO_CHAN_INFO_OFFSET),			\
1988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_index = (_chan),				\
1998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_type = {					\
2008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.sign = (_sign),			\
2018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.realbits = 12,				\
2028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.storagebits = 16,			\
2038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.shift = 2,				\
2048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.endianness = IIO_BE,			\
2058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},						\
2068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS(_name, _sign) \
2098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_##_name[] = { \
2108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(0, (_sign)), \
2118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(1, (_sign)), \
2128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(2, (_sign)), \
2138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(3, (_sign)), \
2148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(4, (_sign)), \
2158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(5, (_sign)), \
2168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(6, (_sign)), \
2178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(7, (_sign)), \
2188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(8, (_sign)), \
2198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(9, (_sign)), \
2208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(10, (_sign)), \
2218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(11, (_sign)), \
2228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(13), \
2238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(_name, _sign) \
2268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_##_name##_fixed[] = { \
2278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(0, (_sign)), \
2288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN(1, (_sign)), \
2298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(2), \
2308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS(u, 'u');
2338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS(s, 's');
2348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(u, 'u');
2358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_SINGLE_ENDED_CHANNELS_FIXED(s, 's');
2368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN_DIFF(_chan, _sign) {			\
2388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.type = IIO_VOLTAGE,				\
2398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.indexed = 1,					\
2408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel = (_chan) * 2,				\
2418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.channel2 = (_chan) * 2 + 1,			\
2428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.address = (_chan),				\
2433234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
2443234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE)	\
2453234ac7e6a96046bd2c996ed93cf843057c3e627Jonathan Cameron		| BIT(IIO_CHAN_INFO_OFFSET),			\
2468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_index = (_chan),				\
2478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.scan_type = {					\
2488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.sign = _sign,			\
2498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.realbits = 12,				\
2508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.storagebits = 16,			\
2518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.shift = 2,				\
2528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.endianness = IIO_BE,			\
2538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},						\
2548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.differential = 1,				\
2558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_DIFF_CHANNELS(_name, _sign) \
2588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_diff_##_name[] = { \
2598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(0, (_sign)), \
2608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(1, (_sign)), \
2618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(2, (_sign)), \
2628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(3, (_sign)), \
2638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(4, (_sign)), \
2648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(5, (_sign)), \
2658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(6), \
2668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS(s, 's');
2698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS(u, 'u');
2708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_DECLARE_DIFF_CHANNELS_FIXED(_name, _sign) \
2728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenconst struct iio_chan_spec ad7266_channels_diff_fixed_##_name[] = { \
2738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(0, (_sign)), \
2748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	AD7266_CHAN_DIFF(1, (_sign)), \
2758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	IIO_CHAN_SOFT_TIMESTAMP(2), \
2768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
2778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS_FIXED(s, 's');
2798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic AD7266_DECLARE_DIFF_CHANNELS_FIXED(u, 'u');
2808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct iio_info ad7266_info = {
2828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.read_raw = &ad7266_read_raw,
2838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.update_scan_mode = &ad7266_update_scan_mode,
2848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.driver_module = THIS_MODULE,
2858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
2868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2872bdb3afcecff232b8670648755a222494d00981dPeter Meerwaldstatic const unsigned long ad7266_available_scan_masks[] = {
2888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
2898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x00c,
2908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x030,
2918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x0c0,
2928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x300,
2938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0xc00,
2948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
2958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
2968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
2972bdb3afcecff232b8670648755a222494d00981dPeter Meerwaldstatic const unsigned long ad7266_available_scan_masks_diff[] = {
2988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
2998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x00c,
3008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x030,
3018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3042bdb3afcecff232b8670648755a222494d00981dPeter Meerwaldstatic const unsigned long ad7266_available_scan_masks_fixed[] = {
3058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x003,
3068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	0x000,
3078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstruct ad7266_chan_info {
3108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const struct iio_chan_spec *channels;
3118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int num_channels;
3122bdb3afcecff232b8670648755a222494d00981dPeter Meerwald	const unsigned long *scan_masks;
3138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen#define AD7266_CHAN_INFO_INDEX(_differential, _signed, _fixed) \
3168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	(((_differential) << 2) | ((_signed) << 1) | ((_fixed) << 0))
3178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct ad7266_chan_info ad7266_chan_infos[] = {
3198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 0, 0)] = {
3208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_u,
3218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_u),
3228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks,
3238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 0, 1)] = {
3258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_u_fixed,
3268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_u_fixed),
3278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 1, 0)] = {
3308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_s,
3318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_s),
3328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks,
3338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(0, 1, 1)] = {
3358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_s_fixed,
3368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_s_fixed),
3378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 0, 0)] = {
3408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_u,
3418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_u),
3428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_diff,
3438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 0, 1)] = {
3458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_fixed_u,
3468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_u),
3478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3488ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 1, 0)] = {
3508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_s,
3518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_s),
3528ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_diff,
3538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	[AD7266_CHAN_INFO_INDEX(1, 1, 1)] = {
3558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.channels = ad7266_channels_diff_fixed_s,
3568ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.num_channels = ARRAY_SIZE(ad7266_channels_diff_fixed_s),
3578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.scan_masks = ad7266_available_scan_masks_fixed,
3588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
3598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
361fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic void ad7266_init_channels(struct iio_dev *indio_dev)
3628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
3638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
3648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	bool is_differential, is_signed;
3658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	const struct ad7266_chan_info *chan_info;
3668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int i;
3678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	is_differential = st->mode != AD7266_MODE_SINGLE_ENDED;
3698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	is_signed = (st->range == AD7266_RANGE_2VREF) |
3708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		    (st->mode == AD7266_MODE_DIFF);
3718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	i = AD7266_CHAN_INFO_INDEX(is_differential, is_signed, st->fixed_addr);
3738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	chan_info = &ad7266_chan_infos[i];
3748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->channels = chan_info->channels;
3768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->num_channels = chan_info->num_channels;
3778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->available_scan_masks = chan_info->scan_masks;
3788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->masklength = chan_info->num_channels - 1;
3798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
3808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const char * const ad7266_gpio_labels[] = {
3828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	"AD0", "AD1", "AD2",
3838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
3848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
385fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic int ad7266_probe(struct spi_device *spi)
3868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
3878ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_platform_data *pdata = spi->dev.platform_data;
3888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev;
3898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st;
3908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	unsigned int i;
3918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	int ret;
3928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
393ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
3948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (indio_dev == NULL)
3958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		return -ENOMEM;
3968ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
3978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st = iio_priv(indio_dev);
3988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
399ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat	st->reg = devm_regulator_get(&spi->dev, "vref");
4008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg)) {
4018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		ret = regulator_enable(st->reg);
4028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (ret)
403ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat			return ret;
4048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
40536ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin		ret = regulator_get_voltage(st->reg);
40636ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin		if (ret < 0)
40736ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin			goto error_disable_reg;
40836ce0c1c3ab7ea54fa6c2b3a0803c7ab0adcefbfAxel Lin
4092ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen		st->vref_mv = ret / 1000;
4108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	} else {
4118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		/* Use internal reference */
4122ebc39c0bbb30d6f06c3fe65c458e546db275f6dLars-Peter Clausen		st->vref_mv = 2500;
4138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
4148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4158ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (pdata) {
4168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->fixed_addr = pdata->fixed_addr;
4178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->mode = pdata->mode;
4188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->range = pdata->range;
4198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		if (!st->fixed_addr) {
4218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			for (i = 0; i < ARRAY_SIZE(st->gpios); ++i) {
4228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].gpio = pdata->addr_gpios[i];
4238ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].flags = GPIOF_OUT_INIT_LOW;
4248ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				st->gpios[i].label = ad7266_gpio_labels[i];
4258ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			}
4268ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			ret = gpio_request_array(st->gpios,
4278ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				ARRAY_SIZE(st->gpios));
4288ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen			if (ret)
4298ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen				goto error_disable_reg;
4308ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		}
4318ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	} else {
4328ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->fixed_addr = true;
4338ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->range = AD7266_RANGE_VREF;
4348ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		st->mode = AD7266_MODE_DIFF;
4358ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	}
4368ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4378ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_set_drvdata(spi, indio_dev);
4388ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->spi = spi;
4398ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4408ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->dev.parent = &spi->dev;
4418ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->name = spi_get_device_id(spi)->name;
4428ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->modes = INDIO_DIRECT_MODE;
4438ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	indio_dev->info = &ad7266_info;
4448ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4458ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ad7266_init_channels(indio_dev);
4468ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4478ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* wakeup */
44854e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	st->single_xfer[0].rx_buf = &st->data.sample[0];
4498ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].len = 2;
4508ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[0].cs_change = 1;
4518ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* conversion */
45254e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	st->single_xfer[1].rx_buf = st->data.sample;
4538ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].len = 4;
4548ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[1].cs_change = 1;
4558ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	/* powerdown */
45654e018da3141dbb41f3578d48be575087339710fLars-Peter Clausen	st->single_xfer[2].tx_buf = &st->data.sample[0];
4578ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	st->single_xfer[2].len = 1;
4588ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4598ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_init(&st->single_msg);
4608ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[0], &st->single_msg);
4618ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[1], &st->single_msg);
4628ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	spi_message_add_tail(&st->single_xfer[2], &st->single_msg);
4638ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4648ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_triggered_buffer_setup(indio_dev, &iio_pollfunc_store_time,
4658ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		&ad7266_trigger_handler, &iio_triggered_buffer_setup_ops);
4668ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
4678ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		goto error_free_gpios;
4688ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4698ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	ret = iio_device_register(indio_dev);
4708ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (ret)
4718ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		goto error_buffer_cleanup;
4728ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4738ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
4748ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4758ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_buffer_cleanup:
4768ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_triggered_buffer_cleanup(indio_dev);
4778ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_free_gpios:
4788ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!st->fixed_addr)
4798ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
4808ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenerror_disable_reg:
4818ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!IS_ERR_OR_NULL(st->reg))
4828ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_disable(st->reg);
4838ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4848ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return ret;
4858ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
4868ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
487fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartmanstatic int ad7266_remove(struct spi_device *spi)
4888ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen{
4898ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct iio_dev *indio_dev = spi_get_drvdata(spi);
4908ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	struct ad7266_state *st = iio_priv(indio_dev);
4918ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4928ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_device_unregister(indio_dev);
4938ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	iio_triggered_buffer_cleanup(indio_dev);
4948ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	if (!st->fixed_addr)
4958ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		gpio_free_array(st->gpios, ARRAY_SIZE(st->gpios));
496ded4fef934768adee9d31f15831513d7d76c360bSachin Kamat	if (!IS_ERR_OR_NULL(st->reg))
4978ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		regulator_disable(st->reg);
4988ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
4998ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	return 0;
5008ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen}
5018ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5028ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic const struct spi_device_id ad7266_id[] = {
5038ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{"ad7265", 0},
5048ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{"ad7266", 0},
5058ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	{ }
5068ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
5078ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_DEVICE_TABLE(spi, ad7266_id);
5088ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5098ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenstatic struct spi_driver ad7266_driver = {
5108ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.driver = {
5118ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.name	= "ad7266",
5128ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen		.owner	= THIS_MODULE,
5138ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	},
5148ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.probe		= ad7266_probe,
515fc52692c49969ec72595766929b9f54ac402da34Greg Kroah-Hartman	.remove		= ad7266_remove,
5168ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen	.id_table	= ad7266_id,
5178ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen};
5188ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausenmodule_spi_driver(ad7266_driver);
5198ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter Clausen
5208ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
5218ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_DESCRIPTION("Analog Devices AD7266/65 ADC");
5228ec4cf5303e03941fa5fd91bbb9c85bd4ae88c47Lars-Peter ClausenMODULE_LICENSE("GPL v2");
523