162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Copyright (C) 2013 Oskar Andero <oskar.andero@gmail.com>
462306a36Sopenharmony_ci * Copyright (C) 2014 Rose Technology
562306a36Sopenharmony_ci * 	   Allan Bendorff Jensen <abj@rosetechnology.dk>
662306a36Sopenharmony_ci *	   Soren Andersen <san@rosetechnology.dk>
762306a36Sopenharmony_ci *
862306a36Sopenharmony_ci * Driver for following ADC chips from Microchip Technology's:
962306a36Sopenharmony_ci * 10 Bit converter
1062306a36Sopenharmony_ci * MCP3001
1162306a36Sopenharmony_ci * MCP3002
1262306a36Sopenharmony_ci * MCP3004
1362306a36Sopenharmony_ci * MCP3008
1462306a36Sopenharmony_ci * ------------
1562306a36Sopenharmony_ci * 12 bit converter
1662306a36Sopenharmony_ci * MCP3201
1762306a36Sopenharmony_ci * MCP3202
1862306a36Sopenharmony_ci * MCP3204
1962306a36Sopenharmony_ci * MCP3208
2062306a36Sopenharmony_ci * ------------
2162306a36Sopenharmony_ci * 13 bit converter
2262306a36Sopenharmony_ci * MCP3301
2362306a36Sopenharmony_ci * ------------
2462306a36Sopenharmony_ci * 22 bit converter
2562306a36Sopenharmony_ci * MCP3550
2662306a36Sopenharmony_ci * MCP3551
2762306a36Sopenharmony_ci * MCP3553
2862306a36Sopenharmony_ci *
2962306a36Sopenharmony_ci * Datasheet can be found here:
3062306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21293C.pdf  mcp3001
3162306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21294E.pdf  mcp3002
3262306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21295d.pdf  mcp3004/08
3362306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21290D.pdf  mcp3201
3462306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21034D.pdf  mcp3202
3562306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21298c.pdf  mcp3204/08
3662306a36Sopenharmony_ci * https://ww1.microchip.com/downloads/en/DeviceDoc/21700E.pdf  mcp3301
3762306a36Sopenharmony_ci * http://ww1.microchip.com/downloads/en/DeviceDoc/21950D.pdf  mcp3550/1/3
3862306a36Sopenharmony_ci */
3962306a36Sopenharmony_ci
4062306a36Sopenharmony_ci#include <linux/err.h>
4162306a36Sopenharmony_ci#include <linux/delay.h>
4262306a36Sopenharmony_ci#include <linux/spi/spi.h>
4362306a36Sopenharmony_ci#include <linux/module.h>
4462306a36Sopenharmony_ci#include <linux/mod_devicetable.h>
4562306a36Sopenharmony_ci#include <linux/iio/iio.h>
4662306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
4762306a36Sopenharmony_ci
4862306a36Sopenharmony_cienum {
4962306a36Sopenharmony_ci	mcp3001,
5062306a36Sopenharmony_ci	mcp3002,
5162306a36Sopenharmony_ci	mcp3004,
5262306a36Sopenharmony_ci	mcp3008,
5362306a36Sopenharmony_ci	mcp3201,
5462306a36Sopenharmony_ci	mcp3202,
5562306a36Sopenharmony_ci	mcp3204,
5662306a36Sopenharmony_ci	mcp3208,
5762306a36Sopenharmony_ci	mcp3301,
5862306a36Sopenharmony_ci	mcp3550_50,
5962306a36Sopenharmony_ci	mcp3550_60,
6062306a36Sopenharmony_ci	mcp3551,
6162306a36Sopenharmony_ci	mcp3553,
6262306a36Sopenharmony_ci};
6362306a36Sopenharmony_ci
6462306a36Sopenharmony_cistruct mcp320x_chip_info {
6562306a36Sopenharmony_ci	const struct iio_chan_spec *channels;
6662306a36Sopenharmony_ci	unsigned int num_channels;
6762306a36Sopenharmony_ci	unsigned int resolution;
6862306a36Sopenharmony_ci	unsigned int conv_time; /* usec */
6962306a36Sopenharmony_ci};
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_ci/**
7262306a36Sopenharmony_ci * struct mcp320x - Microchip SPI ADC instance
7362306a36Sopenharmony_ci * @spi: SPI slave (parent of the IIO device)
7462306a36Sopenharmony_ci * @msg: SPI message to select a channel and receive a value from the ADC
7562306a36Sopenharmony_ci * @transfer: SPI transfers used by @msg
7662306a36Sopenharmony_ci * @start_conv_msg: SPI message to start a conversion by briefly asserting CS
7762306a36Sopenharmony_ci * @start_conv_transfer: SPI transfer used by @start_conv_msg
7862306a36Sopenharmony_ci * @reg: regulator generating Vref
7962306a36Sopenharmony_ci * @lock: protects read sequences
8062306a36Sopenharmony_ci * @chip_info: ADC properties
8162306a36Sopenharmony_ci * @tx_buf: buffer for @transfer[0] (not used on single-channel converters)
8262306a36Sopenharmony_ci * @rx_buf: buffer for @transfer[1]
8362306a36Sopenharmony_ci */
8462306a36Sopenharmony_cistruct mcp320x {
8562306a36Sopenharmony_ci	struct spi_device *spi;
8662306a36Sopenharmony_ci	struct spi_message msg;
8762306a36Sopenharmony_ci	struct spi_transfer transfer[2];
8862306a36Sopenharmony_ci	struct spi_message start_conv_msg;
8962306a36Sopenharmony_ci	struct spi_transfer start_conv_transfer;
9062306a36Sopenharmony_ci
9162306a36Sopenharmony_ci	struct regulator *reg;
9262306a36Sopenharmony_ci	struct mutex lock;
9362306a36Sopenharmony_ci	const struct mcp320x_chip_info *chip_info;
9462306a36Sopenharmony_ci
9562306a36Sopenharmony_ci	u8 tx_buf __aligned(IIO_DMA_MINALIGN);
9662306a36Sopenharmony_ci	u8 rx_buf[4];
9762306a36Sopenharmony_ci};
9862306a36Sopenharmony_ci
9962306a36Sopenharmony_cistatic int mcp320x_channel_to_tx_data(int device_index,
10062306a36Sopenharmony_ci			const unsigned int channel, bool differential)
10162306a36Sopenharmony_ci{
10262306a36Sopenharmony_ci	int start_bit = 1;
10362306a36Sopenharmony_ci
10462306a36Sopenharmony_ci	switch (device_index) {
10562306a36Sopenharmony_ci	case mcp3002:
10662306a36Sopenharmony_ci	case mcp3202:
10762306a36Sopenharmony_ci		return ((start_bit << 4) | (!differential << 3) |
10862306a36Sopenharmony_ci							(channel << 2));
10962306a36Sopenharmony_ci	case mcp3004:
11062306a36Sopenharmony_ci	case mcp3204:
11162306a36Sopenharmony_ci	case mcp3008:
11262306a36Sopenharmony_ci	case mcp3208:
11362306a36Sopenharmony_ci		return ((start_bit << 6) | (!differential << 5) |
11462306a36Sopenharmony_ci							(channel << 2));
11562306a36Sopenharmony_ci	default:
11662306a36Sopenharmony_ci		return -EINVAL;
11762306a36Sopenharmony_ci	}
11862306a36Sopenharmony_ci}
11962306a36Sopenharmony_ci
12062306a36Sopenharmony_cistatic int mcp320x_adc_conversion(struct mcp320x *adc, u8 channel,
12162306a36Sopenharmony_ci				  bool differential, int device_index, int *val)
12262306a36Sopenharmony_ci{
12362306a36Sopenharmony_ci	int ret;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	if (adc->chip_info->conv_time) {
12662306a36Sopenharmony_ci		ret = spi_sync(adc->spi, &adc->start_conv_msg);
12762306a36Sopenharmony_ci		if (ret < 0)
12862306a36Sopenharmony_ci			return ret;
12962306a36Sopenharmony_ci
13062306a36Sopenharmony_ci		usleep_range(adc->chip_info->conv_time,
13162306a36Sopenharmony_ci			     adc->chip_info->conv_time + 100);
13262306a36Sopenharmony_ci	}
13362306a36Sopenharmony_ci
13462306a36Sopenharmony_ci	memset(&adc->rx_buf, 0, sizeof(adc->rx_buf));
13562306a36Sopenharmony_ci	if (adc->chip_info->num_channels > 1)
13662306a36Sopenharmony_ci		adc->tx_buf = mcp320x_channel_to_tx_data(device_index, channel,
13762306a36Sopenharmony_ci							 differential);
13862306a36Sopenharmony_ci
13962306a36Sopenharmony_ci	ret = spi_sync(adc->spi, &adc->msg);
14062306a36Sopenharmony_ci	if (ret < 0)
14162306a36Sopenharmony_ci		return ret;
14262306a36Sopenharmony_ci
14362306a36Sopenharmony_ci	switch (device_index) {
14462306a36Sopenharmony_ci	case mcp3001:
14562306a36Sopenharmony_ci		*val = (adc->rx_buf[0] << 5 | adc->rx_buf[1] >> 3);
14662306a36Sopenharmony_ci		return 0;
14762306a36Sopenharmony_ci	case mcp3002:
14862306a36Sopenharmony_ci	case mcp3004:
14962306a36Sopenharmony_ci	case mcp3008:
15062306a36Sopenharmony_ci		*val = (adc->rx_buf[0] << 2 | adc->rx_buf[1] >> 6);
15162306a36Sopenharmony_ci		return 0;
15262306a36Sopenharmony_ci	case mcp3201:
15362306a36Sopenharmony_ci		*val = (adc->rx_buf[0] << 7 | adc->rx_buf[1] >> 1);
15462306a36Sopenharmony_ci		return 0;
15562306a36Sopenharmony_ci	case mcp3202:
15662306a36Sopenharmony_ci	case mcp3204:
15762306a36Sopenharmony_ci	case mcp3208:
15862306a36Sopenharmony_ci		*val = (adc->rx_buf[0] << 4 | adc->rx_buf[1] >> 4);
15962306a36Sopenharmony_ci		return 0;
16062306a36Sopenharmony_ci	case mcp3301:
16162306a36Sopenharmony_ci		*val = sign_extend32((adc->rx_buf[0] & 0x1f) << 8
16262306a36Sopenharmony_ci				    | adc->rx_buf[1], 12);
16362306a36Sopenharmony_ci		return 0;
16462306a36Sopenharmony_ci	case mcp3550_50:
16562306a36Sopenharmony_ci	case mcp3550_60:
16662306a36Sopenharmony_ci	case mcp3551:
16762306a36Sopenharmony_ci	case mcp3553: {
16862306a36Sopenharmony_ci		u32 raw = be32_to_cpup((__be32 *)adc->rx_buf);
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_ci		if (!(adc->spi->mode & SPI_CPOL))
17162306a36Sopenharmony_ci			raw <<= 1; /* strip Data Ready bit in SPI mode 0,0 */
17262306a36Sopenharmony_ci
17362306a36Sopenharmony_ci		/*
17462306a36Sopenharmony_ci		 * If the input is within -vref and vref, bit 21 is the sign.
17562306a36Sopenharmony_ci		 * Up to 12% overrange or underrange are allowed, in which case
17662306a36Sopenharmony_ci		 * bit 23 is the sign and bit 0 to 21 is the value.
17762306a36Sopenharmony_ci		 */
17862306a36Sopenharmony_ci		raw >>= 8;
17962306a36Sopenharmony_ci		if (raw & BIT(22) && raw & BIT(23))
18062306a36Sopenharmony_ci			return -EIO; /* cannot have overrange AND underrange */
18162306a36Sopenharmony_ci		else if (raw & BIT(22))
18262306a36Sopenharmony_ci			raw &= ~BIT(22); /* overrange */
18362306a36Sopenharmony_ci		else if (raw & BIT(23) || raw & BIT(21))
18462306a36Sopenharmony_ci			raw |= GENMASK(31, 22); /* underrange or negative */
18562306a36Sopenharmony_ci
18662306a36Sopenharmony_ci		*val = (s32)raw;
18762306a36Sopenharmony_ci		return 0;
18862306a36Sopenharmony_ci		}
18962306a36Sopenharmony_ci	default:
19062306a36Sopenharmony_ci		return -EINVAL;
19162306a36Sopenharmony_ci	}
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic int mcp320x_read_raw(struct iio_dev *indio_dev,
19562306a36Sopenharmony_ci			    struct iio_chan_spec const *channel, int *val,
19662306a36Sopenharmony_ci			    int *val2, long mask)
19762306a36Sopenharmony_ci{
19862306a36Sopenharmony_ci	struct mcp320x *adc = iio_priv(indio_dev);
19962306a36Sopenharmony_ci	int ret = -EINVAL;
20062306a36Sopenharmony_ci	int device_index = 0;
20162306a36Sopenharmony_ci
20262306a36Sopenharmony_ci	mutex_lock(&adc->lock);
20362306a36Sopenharmony_ci
20462306a36Sopenharmony_ci	device_index = spi_get_device_id(adc->spi)->driver_data;
20562306a36Sopenharmony_ci
20662306a36Sopenharmony_ci	switch (mask) {
20762306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
20862306a36Sopenharmony_ci		ret = mcp320x_adc_conversion(adc, channel->address,
20962306a36Sopenharmony_ci			channel->differential, device_index, val);
21062306a36Sopenharmony_ci		if (ret < 0)
21162306a36Sopenharmony_ci			goto out;
21262306a36Sopenharmony_ci
21362306a36Sopenharmony_ci		ret = IIO_VAL_INT;
21462306a36Sopenharmony_ci		break;
21562306a36Sopenharmony_ci
21662306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
21762306a36Sopenharmony_ci		ret = regulator_get_voltage(adc->reg);
21862306a36Sopenharmony_ci		if (ret < 0)
21962306a36Sopenharmony_ci			goto out;
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_ci		/* convert regulator output voltage to mV */
22262306a36Sopenharmony_ci		*val = ret / 1000;
22362306a36Sopenharmony_ci		*val2 = adc->chip_info->resolution;
22462306a36Sopenharmony_ci		ret = IIO_VAL_FRACTIONAL_LOG2;
22562306a36Sopenharmony_ci		break;
22662306a36Sopenharmony_ci	}
22762306a36Sopenharmony_ci
22862306a36Sopenharmony_ciout:
22962306a36Sopenharmony_ci	mutex_unlock(&adc->lock);
23062306a36Sopenharmony_ci
23162306a36Sopenharmony_ci	return ret;
23262306a36Sopenharmony_ci}
23362306a36Sopenharmony_ci
23462306a36Sopenharmony_ci#define MCP320X_VOLTAGE_CHANNEL(num)				\
23562306a36Sopenharmony_ci	{							\
23662306a36Sopenharmony_ci		.type = IIO_VOLTAGE,				\
23762306a36Sopenharmony_ci		.indexed = 1,					\
23862306a36Sopenharmony_ci		.channel = (num),				\
23962306a36Sopenharmony_ci		.address = (num),				\
24062306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
24162306a36Sopenharmony_ci		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
24262306a36Sopenharmony_ci	}
24362306a36Sopenharmony_ci
24462306a36Sopenharmony_ci#define MCP320X_VOLTAGE_CHANNEL_DIFF(chan1, chan2)		\
24562306a36Sopenharmony_ci	{							\
24662306a36Sopenharmony_ci		.type = IIO_VOLTAGE,				\
24762306a36Sopenharmony_ci		.indexed = 1,					\
24862306a36Sopenharmony_ci		.channel = (chan1),				\
24962306a36Sopenharmony_ci		.channel2 = (chan2),				\
25062306a36Sopenharmony_ci		.address = (chan1),				\
25162306a36Sopenharmony_ci		.differential = 1,				\
25262306a36Sopenharmony_ci		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
25362306a36Sopenharmony_ci		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) \
25462306a36Sopenharmony_ci	}
25562306a36Sopenharmony_ci
25662306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3201_channels[] = {
25762306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
25862306a36Sopenharmony_ci};
25962306a36Sopenharmony_ci
26062306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3202_channels[] = {
26162306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(0),
26262306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(1),
26362306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
26462306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
26562306a36Sopenharmony_ci};
26662306a36Sopenharmony_ci
26762306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3204_channels[] = {
26862306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(0),
26962306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(1),
27062306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(2),
27162306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(3),
27262306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
27362306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
27462306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
27562306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
27662306a36Sopenharmony_ci};
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_cistatic const struct iio_chan_spec mcp3208_channels[] = {
27962306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(0),
28062306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(1),
28162306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(2),
28262306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(3),
28362306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(4),
28462306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(5),
28562306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(6),
28662306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL(7),
28762306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(0, 1),
28862306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(1, 0),
28962306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(2, 3),
29062306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(3, 2),
29162306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(4, 5),
29262306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(5, 4),
29362306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(6, 7),
29462306a36Sopenharmony_ci	MCP320X_VOLTAGE_CHANNEL_DIFF(7, 6),
29562306a36Sopenharmony_ci};
29662306a36Sopenharmony_ci
29762306a36Sopenharmony_cistatic const struct iio_info mcp320x_info = {
29862306a36Sopenharmony_ci	.read_raw = mcp320x_read_raw,
29962306a36Sopenharmony_ci};
30062306a36Sopenharmony_ci
30162306a36Sopenharmony_cistatic const struct mcp320x_chip_info mcp320x_chip_infos[] = {
30262306a36Sopenharmony_ci	[mcp3001] = {
30362306a36Sopenharmony_ci		.channels = mcp3201_channels,
30462306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
30562306a36Sopenharmony_ci		.resolution = 10
30662306a36Sopenharmony_ci	},
30762306a36Sopenharmony_ci	[mcp3002] = {
30862306a36Sopenharmony_ci		.channels = mcp3202_channels,
30962306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3202_channels),
31062306a36Sopenharmony_ci		.resolution = 10
31162306a36Sopenharmony_ci	},
31262306a36Sopenharmony_ci	[mcp3004] = {
31362306a36Sopenharmony_ci		.channels = mcp3204_channels,
31462306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3204_channels),
31562306a36Sopenharmony_ci		.resolution = 10
31662306a36Sopenharmony_ci	},
31762306a36Sopenharmony_ci	[mcp3008] = {
31862306a36Sopenharmony_ci		.channels = mcp3208_channels,
31962306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3208_channels),
32062306a36Sopenharmony_ci		.resolution = 10
32162306a36Sopenharmony_ci	},
32262306a36Sopenharmony_ci	[mcp3201] = {
32362306a36Sopenharmony_ci		.channels = mcp3201_channels,
32462306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
32562306a36Sopenharmony_ci		.resolution = 12
32662306a36Sopenharmony_ci	},
32762306a36Sopenharmony_ci	[mcp3202] = {
32862306a36Sopenharmony_ci		.channels = mcp3202_channels,
32962306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3202_channels),
33062306a36Sopenharmony_ci		.resolution = 12
33162306a36Sopenharmony_ci	},
33262306a36Sopenharmony_ci	[mcp3204] = {
33362306a36Sopenharmony_ci		.channels = mcp3204_channels,
33462306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3204_channels),
33562306a36Sopenharmony_ci		.resolution = 12
33662306a36Sopenharmony_ci	},
33762306a36Sopenharmony_ci	[mcp3208] = {
33862306a36Sopenharmony_ci		.channels = mcp3208_channels,
33962306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3208_channels),
34062306a36Sopenharmony_ci		.resolution = 12
34162306a36Sopenharmony_ci	},
34262306a36Sopenharmony_ci	[mcp3301] = {
34362306a36Sopenharmony_ci		.channels = mcp3201_channels,
34462306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
34562306a36Sopenharmony_ci		.resolution = 13
34662306a36Sopenharmony_ci	},
34762306a36Sopenharmony_ci	[mcp3550_50] = {
34862306a36Sopenharmony_ci		.channels = mcp3201_channels,
34962306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
35062306a36Sopenharmony_ci		.resolution = 21,
35162306a36Sopenharmony_ci		/* 2% max deviation + 144 clock periods to exit shutdown */
35262306a36Sopenharmony_ci		.conv_time = 80000 * 1.02 + 144000 / 102.4,
35362306a36Sopenharmony_ci	},
35462306a36Sopenharmony_ci	[mcp3550_60] = {
35562306a36Sopenharmony_ci		.channels = mcp3201_channels,
35662306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
35762306a36Sopenharmony_ci		.resolution = 21,
35862306a36Sopenharmony_ci		.conv_time = 66670 * 1.02 + 144000 / 122.88,
35962306a36Sopenharmony_ci	},
36062306a36Sopenharmony_ci	[mcp3551] = {
36162306a36Sopenharmony_ci		.channels = mcp3201_channels,
36262306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
36362306a36Sopenharmony_ci		.resolution = 21,
36462306a36Sopenharmony_ci		.conv_time = 73100 * 1.02 + 144000 / 112.64,
36562306a36Sopenharmony_ci	},
36662306a36Sopenharmony_ci	[mcp3553] = {
36762306a36Sopenharmony_ci		.channels = mcp3201_channels,
36862306a36Sopenharmony_ci		.num_channels = ARRAY_SIZE(mcp3201_channels),
36962306a36Sopenharmony_ci		.resolution = 21,
37062306a36Sopenharmony_ci		.conv_time = 16670 * 1.02 + 144000 / 122.88,
37162306a36Sopenharmony_ci	},
37262306a36Sopenharmony_ci};
37362306a36Sopenharmony_ci
37462306a36Sopenharmony_cistatic int mcp320x_probe(struct spi_device *spi)
37562306a36Sopenharmony_ci{
37662306a36Sopenharmony_ci	struct iio_dev *indio_dev;
37762306a36Sopenharmony_ci	struct mcp320x *adc;
37862306a36Sopenharmony_ci	const struct mcp320x_chip_info *chip_info;
37962306a36Sopenharmony_ci	int ret, device_index;
38062306a36Sopenharmony_ci
38162306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*adc));
38262306a36Sopenharmony_ci	if (!indio_dev)
38362306a36Sopenharmony_ci		return -ENOMEM;
38462306a36Sopenharmony_ci
38562306a36Sopenharmony_ci	adc = iio_priv(indio_dev);
38662306a36Sopenharmony_ci	adc->spi = spi;
38762306a36Sopenharmony_ci
38862306a36Sopenharmony_ci	indio_dev->name = spi_get_device_id(spi)->name;
38962306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
39062306a36Sopenharmony_ci	indio_dev->info = &mcp320x_info;
39162306a36Sopenharmony_ci	spi_set_drvdata(spi, indio_dev);
39262306a36Sopenharmony_ci
39362306a36Sopenharmony_ci	device_index = spi_get_device_id(spi)->driver_data;
39462306a36Sopenharmony_ci	chip_info = &mcp320x_chip_infos[device_index];
39562306a36Sopenharmony_ci	indio_dev->channels = chip_info->channels;
39662306a36Sopenharmony_ci	indio_dev->num_channels = chip_info->num_channels;
39762306a36Sopenharmony_ci
39862306a36Sopenharmony_ci	adc->chip_info = chip_info;
39962306a36Sopenharmony_ci
40062306a36Sopenharmony_ci	adc->transfer[0].tx_buf = &adc->tx_buf;
40162306a36Sopenharmony_ci	adc->transfer[0].len = sizeof(adc->tx_buf);
40262306a36Sopenharmony_ci	adc->transfer[1].rx_buf = adc->rx_buf;
40362306a36Sopenharmony_ci	adc->transfer[1].len = DIV_ROUND_UP(chip_info->resolution, 8);
40462306a36Sopenharmony_ci
40562306a36Sopenharmony_ci	if (chip_info->num_channels == 1)
40662306a36Sopenharmony_ci		/* single-channel converters are rx only (no MOSI pin) */
40762306a36Sopenharmony_ci		spi_message_init_with_transfers(&adc->msg,
40862306a36Sopenharmony_ci						&adc->transfer[1], 1);
40962306a36Sopenharmony_ci	else
41062306a36Sopenharmony_ci		spi_message_init_with_transfers(&adc->msg, adc->transfer,
41162306a36Sopenharmony_ci						ARRAY_SIZE(adc->transfer));
41262306a36Sopenharmony_ci
41362306a36Sopenharmony_ci	switch (device_index) {
41462306a36Sopenharmony_ci	case mcp3550_50:
41562306a36Sopenharmony_ci	case mcp3550_60:
41662306a36Sopenharmony_ci	case mcp3551:
41762306a36Sopenharmony_ci	case mcp3553:
41862306a36Sopenharmony_ci		/* rx len increases from 24 to 25 bit in SPI mode 0,0 */
41962306a36Sopenharmony_ci		if (!(spi->mode & SPI_CPOL))
42062306a36Sopenharmony_ci			adc->transfer[1].len++;
42162306a36Sopenharmony_ci
42262306a36Sopenharmony_ci		/* conversions are started by asserting CS pin for 8 usec */
42362306a36Sopenharmony_ci		adc->start_conv_transfer.delay.value = 8;
42462306a36Sopenharmony_ci		adc->start_conv_transfer.delay.unit = SPI_DELAY_UNIT_USECS;
42562306a36Sopenharmony_ci		spi_message_init_with_transfers(&adc->start_conv_msg,
42662306a36Sopenharmony_ci						&adc->start_conv_transfer, 1);
42762306a36Sopenharmony_ci
42862306a36Sopenharmony_ci		/*
42962306a36Sopenharmony_ci		 * If CS was previously kept low (continuous conversion mode)
43062306a36Sopenharmony_ci		 * and then changed to high, the chip is in shutdown.
43162306a36Sopenharmony_ci		 * Sometimes it fails to wake from shutdown and clocks out
43262306a36Sopenharmony_ci		 * only 0xffffff.  The magic sequence of performing two
43362306a36Sopenharmony_ci		 * conversions without delay between them resets the chip
43462306a36Sopenharmony_ci		 * and ensures all subsequent conversions succeed.
43562306a36Sopenharmony_ci		 */
43662306a36Sopenharmony_ci		mcp320x_adc_conversion(adc, 0, 1, device_index, &ret);
43762306a36Sopenharmony_ci		mcp320x_adc_conversion(adc, 0, 1, device_index, &ret);
43862306a36Sopenharmony_ci	}
43962306a36Sopenharmony_ci
44062306a36Sopenharmony_ci	adc->reg = devm_regulator_get(&spi->dev, "vref");
44162306a36Sopenharmony_ci	if (IS_ERR(adc->reg))
44262306a36Sopenharmony_ci		return PTR_ERR(adc->reg);
44362306a36Sopenharmony_ci
44462306a36Sopenharmony_ci	ret = regulator_enable(adc->reg);
44562306a36Sopenharmony_ci	if (ret < 0)
44662306a36Sopenharmony_ci		return ret;
44762306a36Sopenharmony_ci
44862306a36Sopenharmony_ci	mutex_init(&adc->lock);
44962306a36Sopenharmony_ci
45062306a36Sopenharmony_ci	ret = iio_device_register(indio_dev);
45162306a36Sopenharmony_ci	if (ret < 0)
45262306a36Sopenharmony_ci		goto reg_disable;
45362306a36Sopenharmony_ci
45462306a36Sopenharmony_ci	return 0;
45562306a36Sopenharmony_ci
45662306a36Sopenharmony_cireg_disable:
45762306a36Sopenharmony_ci	regulator_disable(adc->reg);
45862306a36Sopenharmony_ci
45962306a36Sopenharmony_ci	return ret;
46062306a36Sopenharmony_ci}
46162306a36Sopenharmony_ci
46262306a36Sopenharmony_cistatic void mcp320x_remove(struct spi_device *spi)
46362306a36Sopenharmony_ci{
46462306a36Sopenharmony_ci	struct iio_dev *indio_dev = spi_get_drvdata(spi);
46562306a36Sopenharmony_ci	struct mcp320x *adc = iio_priv(indio_dev);
46662306a36Sopenharmony_ci
46762306a36Sopenharmony_ci	iio_device_unregister(indio_dev);
46862306a36Sopenharmony_ci	regulator_disable(adc->reg);
46962306a36Sopenharmony_ci}
47062306a36Sopenharmony_ci
47162306a36Sopenharmony_cistatic const struct of_device_id mcp320x_dt_ids[] = {
47262306a36Sopenharmony_ci	/* NOTE: The use of compatibles with no vendor prefix is deprecated. */
47362306a36Sopenharmony_ci	{ .compatible = "mcp3001" },
47462306a36Sopenharmony_ci	{ .compatible = "mcp3002" },
47562306a36Sopenharmony_ci	{ .compatible = "mcp3004" },
47662306a36Sopenharmony_ci	{ .compatible = "mcp3008" },
47762306a36Sopenharmony_ci	{ .compatible = "mcp3201" },
47862306a36Sopenharmony_ci	{ .compatible = "mcp3202" },
47962306a36Sopenharmony_ci	{ .compatible = "mcp3204" },
48062306a36Sopenharmony_ci	{ .compatible = "mcp3208" },
48162306a36Sopenharmony_ci	{ .compatible = "mcp3301" },
48262306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3001" },
48362306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3002" },
48462306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3004" },
48562306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3008" },
48662306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3201" },
48762306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3202" },
48862306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3204" },
48962306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3208" },
49062306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3301" },
49162306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3550-50" },
49262306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3550-60" },
49362306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3551" },
49462306a36Sopenharmony_ci	{ .compatible = "microchip,mcp3553" },
49562306a36Sopenharmony_ci	{ }
49662306a36Sopenharmony_ci};
49762306a36Sopenharmony_ciMODULE_DEVICE_TABLE(of, mcp320x_dt_ids);
49862306a36Sopenharmony_ci
49962306a36Sopenharmony_cistatic const struct spi_device_id mcp320x_id[] = {
50062306a36Sopenharmony_ci	{ "mcp3001", mcp3001 },
50162306a36Sopenharmony_ci	{ "mcp3002", mcp3002 },
50262306a36Sopenharmony_ci	{ "mcp3004", mcp3004 },
50362306a36Sopenharmony_ci	{ "mcp3008", mcp3008 },
50462306a36Sopenharmony_ci	{ "mcp3201", mcp3201 },
50562306a36Sopenharmony_ci	{ "mcp3202", mcp3202 },
50662306a36Sopenharmony_ci	{ "mcp3204", mcp3204 },
50762306a36Sopenharmony_ci	{ "mcp3208", mcp3208 },
50862306a36Sopenharmony_ci	{ "mcp3301", mcp3301 },
50962306a36Sopenharmony_ci	{ "mcp3550-50", mcp3550_50 },
51062306a36Sopenharmony_ci	{ "mcp3550-60", mcp3550_60 },
51162306a36Sopenharmony_ci	{ "mcp3551", mcp3551 },
51262306a36Sopenharmony_ci	{ "mcp3553", mcp3553 },
51362306a36Sopenharmony_ci	{ }
51462306a36Sopenharmony_ci};
51562306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, mcp320x_id);
51662306a36Sopenharmony_ci
51762306a36Sopenharmony_cistatic struct spi_driver mcp320x_driver = {
51862306a36Sopenharmony_ci	.driver = {
51962306a36Sopenharmony_ci		.name = "mcp320x",
52062306a36Sopenharmony_ci		.of_match_table = mcp320x_dt_ids,
52162306a36Sopenharmony_ci	},
52262306a36Sopenharmony_ci	.probe = mcp320x_probe,
52362306a36Sopenharmony_ci	.remove = mcp320x_remove,
52462306a36Sopenharmony_ci	.id_table = mcp320x_id,
52562306a36Sopenharmony_ci};
52662306a36Sopenharmony_cimodule_spi_driver(mcp320x_driver);
52762306a36Sopenharmony_ci
52862306a36Sopenharmony_ciMODULE_AUTHOR("Oskar Andero <oskar.andero@gmail.com>");
52962306a36Sopenharmony_ciMODULE_DESCRIPTION("Microchip Technology MCP3x01/02/04/08 and MCP3550/1/3");
53062306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
531