162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * AD7887 SPI ADC driver
462306a36Sopenharmony_ci *
562306a36Sopenharmony_ci * Copyright 2010-2011 Analog Devices Inc.
662306a36Sopenharmony_ci */
762306a36Sopenharmony_ci
862306a36Sopenharmony_ci#include <linux/device.h>
962306a36Sopenharmony_ci#include <linux/kernel.h>
1062306a36Sopenharmony_ci#include <linux/slab.h>
1162306a36Sopenharmony_ci#include <linux/sysfs.h>
1262306a36Sopenharmony_ci#include <linux/spi/spi.h>
1362306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1462306a36Sopenharmony_ci#include <linux/err.h>
1562306a36Sopenharmony_ci#include <linux/module.h>
1662306a36Sopenharmony_ci#include <linux/interrupt.h>
1762306a36Sopenharmony_ci#include <linux/bitops.h>
1862306a36Sopenharmony_ci
1962306a36Sopenharmony_ci#include <linux/iio/iio.h>
2062306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
2162306a36Sopenharmony_ci#include <linux/iio/buffer.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/iio/trigger_consumer.h>
2462306a36Sopenharmony_ci#include <linux/iio/triggered_buffer.h>
2562306a36Sopenharmony_ci
2662306a36Sopenharmony_ci#include <linux/platform_data/ad7887.h>
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define AD7887_REF_DIS		BIT(5)	/* on-chip reference disable */
2962306a36Sopenharmony_ci#define AD7887_DUAL		BIT(4)	/* dual-channel mode */
3062306a36Sopenharmony_ci#define AD7887_CH_AIN1		BIT(3)	/* convert on channel 1, DUAL=1 */
3162306a36Sopenharmony_ci#define AD7887_CH_AIN0		0	/* convert on channel 0, DUAL=0,1 */
3262306a36Sopenharmony_ci#define AD7887_PM_MODE1		0	/* CS based shutdown */
3362306a36Sopenharmony_ci#define AD7887_PM_MODE2		1	/* full on */
3462306a36Sopenharmony_ci#define AD7887_PM_MODE3		2	/* auto shutdown after conversion */
3562306a36Sopenharmony_ci#define AD7887_PM_MODE4		3	/* standby mode */
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cienum ad7887_channels {
3862306a36Sopenharmony_ci	AD7887_CH0,
3962306a36Sopenharmony_ci	AD7887_CH0_CH1,
4062306a36Sopenharmony_ci	AD7887_CH1,
4162306a36Sopenharmony_ci};
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci/**
4462306a36Sopenharmony_ci * struct ad7887_chip_info - chip specifc information
4562306a36Sopenharmony_ci * @int_vref_mv:	the internal reference voltage
4662306a36Sopenharmony_ci * @channels:		channels specification
4762306a36Sopenharmony_ci * @num_channels:	number of channels
4862306a36Sopenharmony_ci * @dual_channels:	channels specification in dual mode
4962306a36Sopenharmony_ci * @num_dual_channels:	number of channels in dual mode
5062306a36Sopenharmony_ci */
5162306a36Sopenharmony_cistruct ad7887_chip_info {
5262306a36Sopenharmony_ci	u16				int_vref_mv;
5362306a36Sopenharmony_ci	const struct iio_chan_spec	*channels;
5462306a36Sopenharmony_ci	unsigned int			num_channels;
5562306a36Sopenharmony_ci	const struct iio_chan_spec	*dual_channels;
5662306a36Sopenharmony_ci	unsigned int			num_dual_channels;
5762306a36Sopenharmony_ci};
5862306a36Sopenharmony_ci
5962306a36Sopenharmony_cistruct ad7887_state {
6062306a36Sopenharmony_ci	struct spi_device		*spi;
6162306a36Sopenharmony_ci	const struct ad7887_chip_info	*chip_info;
6262306a36Sopenharmony_ci	struct regulator		*reg;
6362306a36Sopenharmony_ci	struct spi_transfer		xfer[4];
6462306a36Sopenharmony_ci	struct spi_message		msg[3];
6562306a36Sopenharmony_ci	struct spi_message		*ring_msg;
6662306a36Sopenharmony_ci	unsigned char			tx_cmd_buf[4];
6762306a36Sopenharmony_ci
6862306a36Sopenharmony_ci	/*
6962306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) may require the
7062306a36Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
7162306a36Sopenharmony_ci	 * Buffer needs to be large enough to hold two 16 bit samples and a
7262306a36Sopenharmony_ci	 * 64 bit aligned 64 bit timestamp.
7362306a36Sopenharmony_ci	 */
7462306a36Sopenharmony_ci	unsigned char data[ALIGN(4, sizeof(s64)) + sizeof(s64)] __aligned(IIO_DMA_MINALIGN);
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cienum ad7887_supported_device_ids {
7862306a36Sopenharmony_ci	ID_AD7887
7962306a36Sopenharmony_ci};
8062306a36Sopenharmony_ci
8162306a36Sopenharmony_cistatic int ad7887_ring_preenable(struct iio_dev *indio_dev)
8262306a36Sopenharmony_ci{
8362306a36Sopenharmony_ci	struct ad7887_state *st = iio_priv(indio_dev);
8462306a36Sopenharmony_ci
8562306a36Sopenharmony_ci	/* We know this is a single long so can 'cheat' */
8662306a36Sopenharmony_ci	switch (*indio_dev->active_scan_mask) {
8762306a36Sopenharmony_ci	case (1 << 0):
8862306a36Sopenharmony_ci		st->ring_msg = &st->msg[AD7887_CH0];
8962306a36Sopenharmony_ci		break;
9062306a36Sopenharmony_ci	case (1 << 1):
9162306a36Sopenharmony_ci		st->ring_msg = &st->msg[AD7887_CH1];
9262306a36Sopenharmony_ci		/* Dummy read: push CH1 setting down to hardware */
9362306a36Sopenharmony_ci		spi_sync(st->spi, st->ring_msg);
9462306a36Sopenharmony_ci		break;
9562306a36Sopenharmony_ci	case ((1 << 1) | (1 << 0)):
9662306a36Sopenharmony_ci		st->ring_msg = &st->msg[AD7887_CH0_CH1];
9762306a36Sopenharmony_ci		break;
9862306a36Sopenharmony_ci	}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_ci	return 0;
10162306a36Sopenharmony_ci}
10262306a36Sopenharmony_ci
10362306a36Sopenharmony_cistatic int ad7887_ring_postdisable(struct iio_dev *indio_dev)
10462306a36Sopenharmony_ci{
10562306a36Sopenharmony_ci	struct ad7887_state *st = iio_priv(indio_dev);
10662306a36Sopenharmony_ci
10762306a36Sopenharmony_ci	/* dummy read: restore default CH0 settin */
10862306a36Sopenharmony_ci	return spi_sync(st->spi, &st->msg[AD7887_CH0]);
10962306a36Sopenharmony_ci}
11062306a36Sopenharmony_ci
11162306a36Sopenharmony_cistatic irqreturn_t ad7887_trigger_handler(int irq, void *p)
11262306a36Sopenharmony_ci{
11362306a36Sopenharmony_ci	struct iio_poll_func *pf = p;
11462306a36Sopenharmony_ci	struct iio_dev *indio_dev = pf->indio_dev;
11562306a36Sopenharmony_ci	struct ad7887_state *st = iio_priv(indio_dev);
11662306a36Sopenharmony_ci	int b_sent;
11762306a36Sopenharmony_ci
11862306a36Sopenharmony_ci	b_sent = spi_sync(st->spi, st->ring_msg);
11962306a36Sopenharmony_ci	if (b_sent)
12062306a36Sopenharmony_ci		goto done;
12162306a36Sopenharmony_ci
12262306a36Sopenharmony_ci	iio_push_to_buffers_with_timestamp(indio_dev, st->data,
12362306a36Sopenharmony_ci		iio_get_time_ns(indio_dev));
12462306a36Sopenharmony_cidone:
12562306a36Sopenharmony_ci	iio_trigger_notify_done(indio_dev->trig);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ci	return IRQ_HANDLED;
12862306a36Sopenharmony_ci}
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_cistatic const struct iio_buffer_setup_ops ad7887_ring_setup_ops = {
13162306a36Sopenharmony_ci	.preenable = &ad7887_ring_preenable,
13262306a36Sopenharmony_ci	.postdisable = &ad7887_ring_postdisable,
13362306a36Sopenharmony_ci};
13462306a36Sopenharmony_ci
13562306a36Sopenharmony_cistatic int ad7887_scan_direct(struct ad7887_state *st, unsigned ch)
13662306a36Sopenharmony_ci{
13762306a36Sopenharmony_ci	int ret = spi_sync(st->spi, &st->msg[ch]);
13862306a36Sopenharmony_ci	if (ret)
13962306a36Sopenharmony_ci		return ret;
14062306a36Sopenharmony_ci
14162306a36Sopenharmony_ci	return (st->data[(ch * 2)] << 8) | st->data[(ch * 2) + 1];
14262306a36Sopenharmony_ci}
14362306a36Sopenharmony_ci
14462306a36Sopenharmony_cistatic int ad7887_read_raw(struct iio_dev *indio_dev,
14562306a36Sopenharmony_ci			   struct iio_chan_spec const *chan,
14662306a36Sopenharmony_ci			   int *val,
14762306a36Sopenharmony_ci			   int *val2,
14862306a36Sopenharmony_ci			   long m)
14962306a36Sopenharmony_ci{
15062306a36Sopenharmony_ci	int ret;
15162306a36Sopenharmony_ci	struct ad7887_state *st = iio_priv(indio_dev);
15262306a36Sopenharmony_ci
15362306a36Sopenharmony_ci	switch (m) {
15462306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
15562306a36Sopenharmony_ci		ret = iio_device_claim_direct_mode(indio_dev);
15662306a36Sopenharmony_ci		if (ret)
15762306a36Sopenharmony_ci			return ret;
15862306a36Sopenharmony_ci		ret = ad7887_scan_direct(st, chan->address);
15962306a36Sopenharmony_ci		iio_device_release_direct_mode(indio_dev);
16062306a36Sopenharmony_ci
16162306a36Sopenharmony_ci		if (ret < 0)
16262306a36Sopenharmony_ci			return ret;
16362306a36Sopenharmony_ci		*val = ret >> chan->scan_type.shift;
16462306a36Sopenharmony_ci		*val &= GENMASK(chan->scan_type.realbits - 1, 0);
16562306a36Sopenharmony_ci		return IIO_VAL_INT;
16662306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
16762306a36Sopenharmony_ci		if (st->reg) {
16862306a36Sopenharmony_ci			*val = regulator_get_voltage(st->reg);
16962306a36Sopenharmony_ci			if (*val < 0)
17062306a36Sopenharmony_ci				return *val;
17162306a36Sopenharmony_ci			*val /= 1000;
17262306a36Sopenharmony_ci		} else {
17362306a36Sopenharmony_ci			*val = st->chip_info->int_vref_mv;
17462306a36Sopenharmony_ci		}
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci		*val2 = chan->scan_type.realbits;
17762306a36Sopenharmony_ci
17862306a36Sopenharmony_ci		return IIO_VAL_FRACTIONAL_LOG2;
17962306a36Sopenharmony_ci	}
18062306a36Sopenharmony_ci	return -EINVAL;
18162306a36Sopenharmony_ci}
18262306a36Sopenharmony_ci
18362306a36Sopenharmony_ci#define AD7887_CHANNEL(x) { \
18462306a36Sopenharmony_ci	.type = IIO_VOLTAGE, \
18562306a36Sopenharmony_ci	.indexed = 1, \
18662306a36Sopenharmony_ci	.channel = (x), \
18762306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW), \
18862306a36Sopenharmony_ci	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE), \
18962306a36Sopenharmony_ci	.address = (x), \
19062306a36Sopenharmony_ci	.scan_index = (x), \
19162306a36Sopenharmony_ci	.scan_type = { \
19262306a36Sopenharmony_ci		.sign = 'u', \
19362306a36Sopenharmony_ci		.realbits = 12, \
19462306a36Sopenharmony_ci		.storagebits = 16, \
19562306a36Sopenharmony_ci		.shift = 0, \
19662306a36Sopenharmony_ci		.endianness = IIO_BE, \
19762306a36Sopenharmony_ci	}, \
19862306a36Sopenharmony_ci}
19962306a36Sopenharmony_ci
20062306a36Sopenharmony_cistatic const struct iio_chan_spec ad7887_channels[] = {
20162306a36Sopenharmony_ci	AD7887_CHANNEL(0),
20262306a36Sopenharmony_ci	IIO_CHAN_SOFT_TIMESTAMP(1),
20362306a36Sopenharmony_ci};
20462306a36Sopenharmony_ci
20562306a36Sopenharmony_cistatic const struct iio_chan_spec ad7887_dual_channels[] = {
20662306a36Sopenharmony_ci	AD7887_CHANNEL(0),
20762306a36Sopenharmony_ci	AD7887_CHANNEL(1),
20862306a36Sopenharmony_ci	IIO_CHAN_SOFT_TIMESTAMP(2),
20962306a36Sopenharmony_ci};
21062306a36Sopenharmony_ci
21162306a36Sopenharmony_cistatic const struct ad7887_chip_info ad7887_chip_info_tbl[] = {
21262306a36Sopenharmony_ci	/*
21362306a36Sopenharmony_ci	 * More devices added in future
21462306a36Sopenharmony_ci	 */
21562306a36Sopenharmony_ci	[ID_AD7887] = {
21662306a36Sopenharmony_ci		.channels = ad7887_channels,
21762306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(ad7887_channels),
21862306a36Sopenharmony_ci		.dual_channels = ad7887_dual_channels,
21962306a36Sopenharmony_ci		.num_dual_channels = ARRAY_SIZE(ad7887_dual_channels),
22062306a36Sopenharmony_ci		.int_vref_mv = 2500,
22162306a36Sopenharmony_ci	},
22262306a36Sopenharmony_ci};
22362306a36Sopenharmony_ci
22462306a36Sopenharmony_cistatic const struct iio_info ad7887_info = {
22562306a36Sopenharmony_ci	.read_raw = &ad7887_read_raw,
22662306a36Sopenharmony_ci};
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_cistatic void ad7887_reg_disable(void *data)
22962306a36Sopenharmony_ci{
23062306a36Sopenharmony_ci	struct regulator *reg = data;
23162306a36Sopenharmony_ci
23262306a36Sopenharmony_ci	regulator_disable(reg);
23362306a36Sopenharmony_ci}
23462306a36Sopenharmony_ci
23562306a36Sopenharmony_cistatic int ad7887_probe(struct spi_device *spi)
23662306a36Sopenharmony_ci{
23762306a36Sopenharmony_ci	struct ad7887_platform_data *pdata = spi->dev.platform_data;
23862306a36Sopenharmony_ci	struct ad7887_state *st;
23962306a36Sopenharmony_ci	struct iio_dev *indio_dev;
24062306a36Sopenharmony_ci	uint8_t mode;
24162306a36Sopenharmony_ci	int ret;
24262306a36Sopenharmony_ci
24362306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
24462306a36Sopenharmony_ci	if (indio_dev == NULL)
24562306a36Sopenharmony_ci		return -ENOMEM;
24662306a36Sopenharmony_ci
24762306a36Sopenharmony_ci	st = iio_priv(indio_dev);
24862306a36Sopenharmony_ci
24962306a36Sopenharmony_ci	st->reg = devm_regulator_get_optional(&spi->dev, "vref");
25062306a36Sopenharmony_ci	if (IS_ERR(st->reg)) {
25162306a36Sopenharmony_ci		if (PTR_ERR(st->reg) != -ENODEV)
25262306a36Sopenharmony_ci			return PTR_ERR(st->reg);
25362306a36Sopenharmony_ci
25462306a36Sopenharmony_ci		st->reg = NULL;
25562306a36Sopenharmony_ci	}
25662306a36Sopenharmony_ci
25762306a36Sopenharmony_ci	if (st->reg) {
25862306a36Sopenharmony_ci		ret = regulator_enable(st->reg);
25962306a36Sopenharmony_ci		if (ret)
26062306a36Sopenharmony_ci			return ret;
26162306a36Sopenharmony_ci
26262306a36Sopenharmony_ci		ret = devm_add_action_or_reset(&spi->dev, ad7887_reg_disable, st->reg);
26362306a36Sopenharmony_ci		if (ret)
26462306a36Sopenharmony_ci			return ret;
26562306a36Sopenharmony_ci	}
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_ci	st->chip_info =
26862306a36Sopenharmony_ci		&ad7887_chip_info_tbl[spi_get_device_id(spi)->driver_data];
26962306a36Sopenharmony_ci
27062306a36Sopenharmony_ci	st->spi = spi;
27162306a36Sopenharmony_ci
27262306a36Sopenharmony_ci	indio_dev->name = spi_get_device_id(spi)->name;
27362306a36Sopenharmony_ci	indio_dev->info = &ad7887_info;
27462306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
27562306a36Sopenharmony_ci
27662306a36Sopenharmony_ci	/* Setup default message */
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	mode = AD7887_PM_MODE4;
27962306a36Sopenharmony_ci	if (!st->reg)
28062306a36Sopenharmony_ci		mode |= AD7887_REF_DIS;
28162306a36Sopenharmony_ci	if (pdata && pdata->en_dual)
28262306a36Sopenharmony_ci		mode |= AD7887_DUAL;
28362306a36Sopenharmony_ci
28462306a36Sopenharmony_ci	st->tx_cmd_buf[0] = AD7887_CH_AIN0 | mode;
28562306a36Sopenharmony_ci
28662306a36Sopenharmony_ci	st->xfer[0].rx_buf = &st->data[0];
28762306a36Sopenharmony_ci	st->xfer[0].tx_buf = &st->tx_cmd_buf[0];
28862306a36Sopenharmony_ci	st->xfer[0].len = 2;
28962306a36Sopenharmony_ci
29062306a36Sopenharmony_ci	spi_message_init(&st->msg[AD7887_CH0]);
29162306a36Sopenharmony_ci	spi_message_add_tail(&st->xfer[0], &st->msg[AD7887_CH0]);
29262306a36Sopenharmony_ci
29362306a36Sopenharmony_ci	if (pdata && pdata->en_dual) {
29462306a36Sopenharmony_ci		st->tx_cmd_buf[2] = AD7887_CH_AIN1 | mode;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci		st->xfer[1].rx_buf = &st->data[0];
29762306a36Sopenharmony_ci		st->xfer[1].tx_buf = &st->tx_cmd_buf[2];
29862306a36Sopenharmony_ci		st->xfer[1].len = 2;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci		st->xfer[2].rx_buf = &st->data[2];
30162306a36Sopenharmony_ci		st->xfer[2].tx_buf = &st->tx_cmd_buf[0];
30262306a36Sopenharmony_ci		st->xfer[2].len = 2;
30362306a36Sopenharmony_ci
30462306a36Sopenharmony_ci		spi_message_init(&st->msg[AD7887_CH0_CH1]);
30562306a36Sopenharmony_ci		spi_message_add_tail(&st->xfer[1], &st->msg[AD7887_CH0_CH1]);
30662306a36Sopenharmony_ci		spi_message_add_tail(&st->xfer[2], &st->msg[AD7887_CH0_CH1]);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci		st->xfer[3].rx_buf = &st->data[2];
30962306a36Sopenharmony_ci		st->xfer[3].tx_buf = &st->tx_cmd_buf[2];
31062306a36Sopenharmony_ci		st->xfer[3].len = 2;
31162306a36Sopenharmony_ci
31262306a36Sopenharmony_ci		spi_message_init(&st->msg[AD7887_CH1]);
31362306a36Sopenharmony_ci		spi_message_add_tail(&st->xfer[3], &st->msg[AD7887_CH1]);
31462306a36Sopenharmony_ci
31562306a36Sopenharmony_ci		indio_dev->channels = st->chip_info->dual_channels;
31662306a36Sopenharmony_ci		indio_dev->num_channels = st->chip_info->num_dual_channels;
31762306a36Sopenharmony_ci	} else {
31862306a36Sopenharmony_ci		indio_dev->channels = st->chip_info->channels;
31962306a36Sopenharmony_ci		indio_dev->num_channels = st->chip_info->num_channels;
32062306a36Sopenharmony_ci	}
32162306a36Sopenharmony_ci
32262306a36Sopenharmony_ci	ret = devm_iio_triggered_buffer_setup(&spi->dev, indio_dev,
32362306a36Sopenharmony_ci			&iio_pollfunc_store_time,
32462306a36Sopenharmony_ci			&ad7887_trigger_handler, &ad7887_ring_setup_ops);
32562306a36Sopenharmony_ci	if (ret)
32662306a36Sopenharmony_ci		return ret;
32762306a36Sopenharmony_ci
32862306a36Sopenharmony_ci	return devm_iio_device_register(&spi->dev, indio_dev);
32962306a36Sopenharmony_ci}
33062306a36Sopenharmony_ci
33162306a36Sopenharmony_cistatic const struct spi_device_id ad7887_id[] = {
33262306a36Sopenharmony_ci	{"ad7887", ID_AD7887},
33362306a36Sopenharmony_ci	{}
33462306a36Sopenharmony_ci};
33562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad7887_id);
33662306a36Sopenharmony_ci
33762306a36Sopenharmony_cistatic struct spi_driver ad7887_driver = {
33862306a36Sopenharmony_ci	.driver = {
33962306a36Sopenharmony_ci		.name	= "ad7887",
34062306a36Sopenharmony_ci	},
34162306a36Sopenharmony_ci	.probe		= ad7887_probe,
34262306a36Sopenharmony_ci	.id_table	= ad7887_id,
34362306a36Sopenharmony_ci};
34462306a36Sopenharmony_cimodule_spi_driver(ad7887_driver);
34562306a36Sopenharmony_ci
34662306a36Sopenharmony_ciMODULE_AUTHOR("Michael Hennerich <michael.hennerich@analog.com>");
34762306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD7887 ADC");
34862306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
349