162306a36Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0-only
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * AD5415, AD5426, AD5429, AD5432, AD5439, AD5443, AD5449 Digital to Analog
462306a36Sopenharmony_ci * Converter driver.
562306a36Sopenharmony_ci *
662306a36Sopenharmony_ci * Copyright 2012 Analog Devices Inc.
762306a36Sopenharmony_ci *  Author: Lars-Peter Clausen <lars@metafoo.de>
862306a36Sopenharmony_ci */
962306a36Sopenharmony_ci
1062306a36Sopenharmony_ci#include <linux/device.h>
1162306a36Sopenharmony_ci#include <linux/err.h>
1262306a36Sopenharmony_ci#include <linux/module.h>
1362306a36Sopenharmony_ci#include <linux/kernel.h>
1462306a36Sopenharmony_ci#include <linux/spi/spi.h>
1562306a36Sopenharmony_ci#include <linux/slab.h>
1662306a36Sopenharmony_ci#include <linux/sysfs.h>
1762306a36Sopenharmony_ci#include <linux/regulator/consumer.h>
1862306a36Sopenharmony_ci#include <asm/unaligned.h>
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_ci#include <linux/iio/iio.h>
2162306a36Sopenharmony_ci#include <linux/iio/sysfs.h>
2262306a36Sopenharmony_ci
2362306a36Sopenharmony_ci#include <linux/platform_data/ad5449.h>
2462306a36Sopenharmony_ci
2562306a36Sopenharmony_ci#define AD5449_MAX_CHANNELS		2
2662306a36Sopenharmony_ci#define AD5449_MAX_VREFS		2
2762306a36Sopenharmony_ci
2862306a36Sopenharmony_ci#define AD5449_CMD_NOOP			0x0
2962306a36Sopenharmony_ci#define AD5449_CMD_LOAD_AND_UPDATE(x)	(0x1 + (x) * 3)
3062306a36Sopenharmony_ci#define AD5449_CMD_READ(x)		(0x2 + (x) * 3)
3162306a36Sopenharmony_ci#define AD5449_CMD_LOAD(x)		(0x3 + (x) * 3)
3262306a36Sopenharmony_ci#define AD5449_CMD_CTRL			13
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#define AD5449_CTRL_SDO_OFFSET		10
3562306a36Sopenharmony_ci#define AD5449_CTRL_DAISY_CHAIN		BIT(9)
3662306a36Sopenharmony_ci#define AD5449_CTRL_HCLR_TO_MIDSCALE	BIT(8)
3762306a36Sopenharmony_ci#define AD5449_CTRL_SAMPLE_RISING	BIT(7)
3862306a36Sopenharmony_ci
3962306a36Sopenharmony_ci/**
4062306a36Sopenharmony_ci * struct ad5449_chip_info - chip specific information
4162306a36Sopenharmony_ci * @channels:		Channel specification
4262306a36Sopenharmony_ci * @num_channels:	Number of channels
4362306a36Sopenharmony_ci * @has_ctrl:		Chip has a control register
4462306a36Sopenharmony_ci */
4562306a36Sopenharmony_cistruct ad5449_chip_info {
4662306a36Sopenharmony_ci	const struct iio_chan_spec *channels;
4762306a36Sopenharmony_ci	unsigned int num_channels;
4862306a36Sopenharmony_ci	bool has_ctrl;
4962306a36Sopenharmony_ci};
5062306a36Sopenharmony_ci
5162306a36Sopenharmony_ci/**
5262306a36Sopenharmony_ci * struct ad5449 - driver instance specific data
5362306a36Sopenharmony_ci * @spi:		the SPI device for this driver instance
5462306a36Sopenharmony_ci * @chip_info:		chip model specific constants, available modes etc
5562306a36Sopenharmony_ci * @vref_reg:		vref supply regulators
5662306a36Sopenharmony_ci * @has_sdo:		whether the SDO line is connected
5762306a36Sopenharmony_ci * @dac_cache:		Cache for the DAC values
5862306a36Sopenharmony_ci * @data:		spi transfer buffers
5962306a36Sopenharmony_ci * @lock:		lock to protect the data buffer during SPI ops
6062306a36Sopenharmony_ci */
6162306a36Sopenharmony_cistruct ad5449 {
6262306a36Sopenharmony_ci	struct spi_device		*spi;
6362306a36Sopenharmony_ci	const struct ad5449_chip_info	*chip_info;
6462306a36Sopenharmony_ci	struct regulator_bulk_data	vref_reg[AD5449_MAX_VREFS];
6562306a36Sopenharmony_ci	struct mutex			lock;
6662306a36Sopenharmony_ci
6762306a36Sopenharmony_ci	bool has_sdo;
6862306a36Sopenharmony_ci	uint16_t dac_cache[AD5449_MAX_CHANNELS];
6962306a36Sopenharmony_ci
7062306a36Sopenharmony_ci	/*
7162306a36Sopenharmony_ci	 * DMA (thus cache coherency maintenance) may require the
7262306a36Sopenharmony_ci	 * transfer buffers to live in their own cache lines.
7362306a36Sopenharmony_ci	 */
7462306a36Sopenharmony_ci	__be16 data[2] __aligned(IIO_DMA_MINALIGN);
7562306a36Sopenharmony_ci};
7662306a36Sopenharmony_ci
7762306a36Sopenharmony_cienum ad5449_type {
7862306a36Sopenharmony_ci	ID_AD5426,
7962306a36Sopenharmony_ci	ID_AD5429,
8062306a36Sopenharmony_ci	ID_AD5432,
8162306a36Sopenharmony_ci	ID_AD5439,
8262306a36Sopenharmony_ci	ID_AD5443,
8362306a36Sopenharmony_ci	ID_AD5449,
8462306a36Sopenharmony_ci};
8562306a36Sopenharmony_ci
8662306a36Sopenharmony_cistatic int ad5449_write(struct iio_dev *indio_dev, unsigned int addr,
8762306a36Sopenharmony_ci	unsigned int val)
8862306a36Sopenharmony_ci{
8962306a36Sopenharmony_ci	struct ad5449 *st = iio_priv(indio_dev);
9062306a36Sopenharmony_ci	int ret;
9162306a36Sopenharmony_ci
9262306a36Sopenharmony_ci	mutex_lock(&st->lock);
9362306a36Sopenharmony_ci	st->data[0] = cpu_to_be16((addr << 12) | val);
9462306a36Sopenharmony_ci	ret = spi_write(st->spi, st->data, 2);
9562306a36Sopenharmony_ci	mutex_unlock(&st->lock);
9662306a36Sopenharmony_ci
9762306a36Sopenharmony_ci	return ret;
9862306a36Sopenharmony_ci}
9962306a36Sopenharmony_ci
10062306a36Sopenharmony_cistatic int ad5449_read(struct iio_dev *indio_dev, unsigned int addr,
10162306a36Sopenharmony_ci	unsigned int *val)
10262306a36Sopenharmony_ci{
10362306a36Sopenharmony_ci	struct ad5449 *st = iio_priv(indio_dev);
10462306a36Sopenharmony_ci	int ret;
10562306a36Sopenharmony_ci	struct spi_transfer t[] = {
10662306a36Sopenharmony_ci		{
10762306a36Sopenharmony_ci			.tx_buf = &st->data[0],
10862306a36Sopenharmony_ci			.len = 2,
10962306a36Sopenharmony_ci			.cs_change = 1,
11062306a36Sopenharmony_ci		}, {
11162306a36Sopenharmony_ci			.tx_buf = &st->data[1],
11262306a36Sopenharmony_ci			.rx_buf = &st->data[1],
11362306a36Sopenharmony_ci			.len = 2,
11462306a36Sopenharmony_ci		},
11562306a36Sopenharmony_ci	};
11662306a36Sopenharmony_ci
11762306a36Sopenharmony_ci	mutex_lock(&st->lock);
11862306a36Sopenharmony_ci	st->data[0] = cpu_to_be16(addr << 12);
11962306a36Sopenharmony_ci	st->data[1] = cpu_to_be16(AD5449_CMD_NOOP);
12062306a36Sopenharmony_ci
12162306a36Sopenharmony_ci	ret = spi_sync_transfer(st->spi, t, ARRAY_SIZE(t));
12262306a36Sopenharmony_ci	if (ret < 0)
12362306a36Sopenharmony_ci		goto out_unlock;
12462306a36Sopenharmony_ci
12562306a36Sopenharmony_ci	*val = be16_to_cpu(st->data[1]);
12662306a36Sopenharmony_ci
12762306a36Sopenharmony_ciout_unlock:
12862306a36Sopenharmony_ci	mutex_unlock(&st->lock);
12962306a36Sopenharmony_ci	return ret;
13062306a36Sopenharmony_ci}
13162306a36Sopenharmony_ci
13262306a36Sopenharmony_cistatic int ad5449_read_raw(struct iio_dev *indio_dev,
13362306a36Sopenharmony_ci	struct iio_chan_spec const *chan, int *val, int *val2, long info)
13462306a36Sopenharmony_ci{
13562306a36Sopenharmony_ci	struct ad5449 *st = iio_priv(indio_dev);
13662306a36Sopenharmony_ci	struct regulator_bulk_data *reg;
13762306a36Sopenharmony_ci	int scale_uv;
13862306a36Sopenharmony_ci	int ret;
13962306a36Sopenharmony_ci
14062306a36Sopenharmony_ci	switch (info) {
14162306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
14262306a36Sopenharmony_ci		if (st->has_sdo) {
14362306a36Sopenharmony_ci			ret = ad5449_read(indio_dev,
14462306a36Sopenharmony_ci				AD5449_CMD_READ(chan->address), val);
14562306a36Sopenharmony_ci			if (ret)
14662306a36Sopenharmony_ci				return ret;
14762306a36Sopenharmony_ci			*val &= 0xfff;
14862306a36Sopenharmony_ci		} else {
14962306a36Sopenharmony_ci			*val = st->dac_cache[chan->address];
15062306a36Sopenharmony_ci		}
15162306a36Sopenharmony_ci
15262306a36Sopenharmony_ci		return IIO_VAL_INT;
15362306a36Sopenharmony_ci	case IIO_CHAN_INFO_SCALE:
15462306a36Sopenharmony_ci		reg = &st->vref_reg[chan->channel];
15562306a36Sopenharmony_ci		scale_uv = regulator_get_voltage(reg->consumer);
15662306a36Sopenharmony_ci		if (scale_uv < 0)
15762306a36Sopenharmony_ci			return scale_uv;
15862306a36Sopenharmony_ci
15962306a36Sopenharmony_ci		*val = scale_uv / 1000;
16062306a36Sopenharmony_ci		*val2 = chan->scan_type.realbits;
16162306a36Sopenharmony_ci
16262306a36Sopenharmony_ci		return IIO_VAL_FRACTIONAL_LOG2;
16362306a36Sopenharmony_ci	default:
16462306a36Sopenharmony_ci		break;
16562306a36Sopenharmony_ci	}
16662306a36Sopenharmony_ci
16762306a36Sopenharmony_ci	return -EINVAL;
16862306a36Sopenharmony_ci}
16962306a36Sopenharmony_ci
17062306a36Sopenharmony_cistatic int ad5449_write_raw(struct iio_dev *indio_dev,
17162306a36Sopenharmony_ci	struct iio_chan_spec const *chan, int val, int val2, long info)
17262306a36Sopenharmony_ci{
17362306a36Sopenharmony_ci	struct ad5449 *st = iio_priv(indio_dev);
17462306a36Sopenharmony_ci	int ret;
17562306a36Sopenharmony_ci
17662306a36Sopenharmony_ci	switch (info) {
17762306a36Sopenharmony_ci	case IIO_CHAN_INFO_RAW:
17862306a36Sopenharmony_ci		if (val < 0 || val >= (1 << chan->scan_type.realbits))
17962306a36Sopenharmony_ci			return -EINVAL;
18062306a36Sopenharmony_ci
18162306a36Sopenharmony_ci		ret = ad5449_write(indio_dev,
18262306a36Sopenharmony_ci			AD5449_CMD_LOAD_AND_UPDATE(chan->address),
18362306a36Sopenharmony_ci			val << chan->scan_type.shift);
18462306a36Sopenharmony_ci		if (ret == 0)
18562306a36Sopenharmony_ci			st->dac_cache[chan->address] = val;
18662306a36Sopenharmony_ci		break;
18762306a36Sopenharmony_ci	default:
18862306a36Sopenharmony_ci		ret = -EINVAL;
18962306a36Sopenharmony_ci	}
19062306a36Sopenharmony_ci
19162306a36Sopenharmony_ci	return ret;
19262306a36Sopenharmony_ci}
19362306a36Sopenharmony_ci
19462306a36Sopenharmony_cistatic const struct iio_info ad5449_info = {
19562306a36Sopenharmony_ci	.read_raw = ad5449_read_raw,
19662306a36Sopenharmony_ci	.write_raw = ad5449_write_raw,
19762306a36Sopenharmony_ci};
19862306a36Sopenharmony_ci
19962306a36Sopenharmony_ci#define AD5449_CHANNEL(chan, bits) {				\
20062306a36Sopenharmony_ci	.type = IIO_VOLTAGE,					\
20162306a36Sopenharmony_ci	.indexed = 1,						\
20262306a36Sopenharmony_ci	.output = 1,						\
20362306a36Sopenharmony_ci	.channel = (chan),					\
20462306a36Sopenharmony_ci	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |		\
20562306a36Sopenharmony_ci		BIT(IIO_CHAN_INFO_SCALE),			\
20662306a36Sopenharmony_ci	.address = (chan),					\
20762306a36Sopenharmony_ci	.scan_type = {						\
20862306a36Sopenharmony_ci		.sign = 'u',					\
20962306a36Sopenharmony_ci		.realbits = (bits),				\
21062306a36Sopenharmony_ci		.storagebits = 16,				\
21162306a36Sopenharmony_ci		.shift = 12 - (bits),				\
21262306a36Sopenharmony_ci	},							\
21362306a36Sopenharmony_ci}
21462306a36Sopenharmony_ci
21562306a36Sopenharmony_ci#define DECLARE_AD5449_CHANNELS(name, bits) \
21662306a36Sopenharmony_ciconst struct iio_chan_spec name[] = { \
21762306a36Sopenharmony_ci	AD5449_CHANNEL(0, bits), \
21862306a36Sopenharmony_ci	AD5449_CHANNEL(1, bits), \
21962306a36Sopenharmony_ci}
22062306a36Sopenharmony_ci
22162306a36Sopenharmony_cistatic DECLARE_AD5449_CHANNELS(ad5429_channels, 8);
22262306a36Sopenharmony_cistatic DECLARE_AD5449_CHANNELS(ad5439_channels, 10);
22362306a36Sopenharmony_cistatic DECLARE_AD5449_CHANNELS(ad5449_channels, 12);
22462306a36Sopenharmony_ci
22562306a36Sopenharmony_cistatic const struct ad5449_chip_info ad5449_chip_info[] = {
22662306a36Sopenharmony_ci	[ID_AD5426] = {
22762306a36Sopenharmony_ci		.channels = ad5429_channels,
22862306a36Sopenharmony_ci		.num_channels = 1,
22962306a36Sopenharmony_ci		.has_ctrl = false,
23062306a36Sopenharmony_ci	},
23162306a36Sopenharmony_ci	[ID_AD5429] = {
23262306a36Sopenharmony_ci		.channels = ad5429_channels,
23362306a36Sopenharmony_ci		.num_channels = 2,
23462306a36Sopenharmony_ci		.has_ctrl = true,
23562306a36Sopenharmony_ci	},
23662306a36Sopenharmony_ci	[ID_AD5432] = {
23762306a36Sopenharmony_ci		.channels = ad5439_channels,
23862306a36Sopenharmony_ci		.num_channels = 1,
23962306a36Sopenharmony_ci		.has_ctrl = false,
24062306a36Sopenharmony_ci	},
24162306a36Sopenharmony_ci	[ID_AD5439] = {
24262306a36Sopenharmony_ci		.channels = ad5439_channels,
24362306a36Sopenharmony_ci		.num_channels = 2,
24462306a36Sopenharmony_ci		.has_ctrl = true,
24562306a36Sopenharmony_ci	},
24662306a36Sopenharmony_ci	[ID_AD5443] = {
24762306a36Sopenharmony_ci		.channels = ad5449_channels,
24862306a36Sopenharmony_ci		.num_channels = 1,
24962306a36Sopenharmony_ci		.has_ctrl = false,
25062306a36Sopenharmony_ci	},
25162306a36Sopenharmony_ci	[ID_AD5449] = {
25262306a36Sopenharmony_ci		.channels = ad5449_channels,
25362306a36Sopenharmony_ci		.num_channels = 2,
25462306a36Sopenharmony_ci		.has_ctrl = true,
25562306a36Sopenharmony_ci	},
25662306a36Sopenharmony_ci};
25762306a36Sopenharmony_ci
25862306a36Sopenharmony_cistatic const char *ad5449_vref_name(struct ad5449 *st, int n)
25962306a36Sopenharmony_ci{
26062306a36Sopenharmony_ci	if (st->chip_info->num_channels == 1)
26162306a36Sopenharmony_ci		return "VREF";
26262306a36Sopenharmony_ci
26362306a36Sopenharmony_ci	if (n == 0)
26462306a36Sopenharmony_ci		return "VREFA";
26562306a36Sopenharmony_ci	else
26662306a36Sopenharmony_ci		return "VREFB";
26762306a36Sopenharmony_ci}
26862306a36Sopenharmony_ci
26962306a36Sopenharmony_cistatic int ad5449_spi_probe(struct spi_device *spi)
27062306a36Sopenharmony_ci{
27162306a36Sopenharmony_ci	struct ad5449_platform_data *pdata = spi->dev.platform_data;
27262306a36Sopenharmony_ci	const struct spi_device_id *id = spi_get_device_id(spi);
27362306a36Sopenharmony_ci	struct iio_dev *indio_dev;
27462306a36Sopenharmony_ci	struct ad5449 *st;
27562306a36Sopenharmony_ci	unsigned int i;
27662306a36Sopenharmony_ci	int ret;
27762306a36Sopenharmony_ci
27862306a36Sopenharmony_ci	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*st));
27962306a36Sopenharmony_ci	if (indio_dev == NULL)
28062306a36Sopenharmony_ci		return -ENOMEM;
28162306a36Sopenharmony_ci
28262306a36Sopenharmony_ci	st = iio_priv(indio_dev);
28362306a36Sopenharmony_ci	spi_set_drvdata(spi, indio_dev);
28462306a36Sopenharmony_ci
28562306a36Sopenharmony_ci	st->chip_info = &ad5449_chip_info[id->driver_data];
28662306a36Sopenharmony_ci	st->spi = spi;
28762306a36Sopenharmony_ci
28862306a36Sopenharmony_ci	for (i = 0; i < st->chip_info->num_channels; ++i)
28962306a36Sopenharmony_ci		st->vref_reg[i].supply = ad5449_vref_name(st, i);
29062306a36Sopenharmony_ci
29162306a36Sopenharmony_ci	ret = devm_regulator_bulk_get(&spi->dev, st->chip_info->num_channels,
29262306a36Sopenharmony_ci				st->vref_reg);
29362306a36Sopenharmony_ci	if (ret)
29462306a36Sopenharmony_ci		return ret;
29562306a36Sopenharmony_ci
29662306a36Sopenharmony_ci	ret = regulator_bulk_enable(st->chip_info->num_channels, st->vref_reg);
29762306a36Sopenharmony_ci	if (ret)
29862306a36Sopenharmony_ci		return ret;
29962306a36Sopenharmony_ci
30062306a36Sopenharmony_ci	indio_dev->name = id->name;
30162306a36Sopenharmony_ci	indio_dev->info = &ad5449_info;
30262306a36Sopenharmony_ci	indio_dev->modes = INDIO_DIRECT_MODE;
30362306a36Sopenharmony_ci	indio_dev->channels = st->chip_info->channels;
30462306a36Sopenharmony_ci	indio_dev->num_channels = st->chip_info->num_channels;
30562306a36Sopenharmony_ci
30662306a36Sopenharmony_ci	mutex_init(&st->lock);
30762306a36Sopenharmony_ci
30862306a36Sopenharmony_ci	if (st->chip_info->has_ctrl) {
30962306a36Sopenharmony_ci		unsigned int ctrl = 0x00;
31062306a36Sopenharmony_ci		if (pdata) {
31162306a36Sopenharmony_ci			if (pdata->hardware_clear_to_midscale)
31262306a36Sopenharmony_ci				ctrl |= AD5449_CTRL_HCLR_TO_MIDSCALE;
31362306a36Sopenharmony_ci			ctrl |= pdata->sdo_mode << AD5449_CTRL_SDO_OFFSET;
31462306a36Sopenharmony_ci			st->has_sdo = pdata->sdo_mode != AD5449_SDO_DISABLED;
31562306a36Sopenharmony_ci		} else {
31662306a36Sopenharmony_ci			st->has_sdo = true;
31762306a36Sopenharmony_ci		}
31862306a36Sopenharmony_ci		ad5449_write(indio_dev, AD5449_CMD_CTRL, ctrl);
31962306a36Sopenharmony_ci	}
32062306a36Sopenharmony_ci
32162306a36Sopenharmony_ci	ret = iio_device_register(indio_dev);
32262306a36Sopenharmony_ci	if (ret)
32362306a36Sopenharmony_ci		goto error_disable_reg;
32462306a36Sopenharmony_ci
32562306a36Sopenharmony_ci	return 0;
32662306a36Sopenharmony_ci
32762306a36Sopenharmony_cierror_disable_reg:
32862306a36Sopenharmony_ci	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
32962306a36Sopenharmony_ci
33062306a36Sopenharmony_ci	return ret;
33162306a36Sopenharmony_ci}
33262306a36Sopenharmony_ci
33362306a36Sopenharmony_cistatic void ad5449_spi_remove(struct spi_device *spi)
33462306a36Sopenharmony_ci{
33562306a36Sopenharmony_ci	struct iio_dev *indio_dev = spi_get_drvdata(spi);
33662306a36Sopenharmony_ci	struct ad5449 *st = iio_priv(indio_dev);
33762306a36Sopenharmony_ci
33862306a36Sopenharmony_ci	iio_device_unregister(indio_dev);
33962306a36Sopenharmony_ci
34062306a36Sopenharmony_ci	regulator_bulk_disable(st->chip_info->num_channels, st->vref_reg);
34162306a36Sopenharmony_ci}
34262306a36Sopenharmony_ci
34362306a36Sopenharmony_cistatic const struct spi_device_id ad5449_spi_ids[] = {
34462306a36Sopenharmony_ci	{ "ad5415", ID_AD5449 },
34562306a36Sopenharmony_ci	{ "ad5426", ID_AD5426 },
34662306a36Sopenharmony_ci	{ "ad5429", ID_AD5429 },
34762306a36Sopenharmony_ci	{ "ad5432", ID_AD5432 },
34862306a36Sopenharmony_ci	{ "ad5439", ID_AD5439 },
34962306a36Sopenharmony_ci	{ "ad5443", ID_AD5443 },
35062306a36Sopenharmony_ci	{ "ad5449", ID_AD5449 },
35162306a36Sopenharmony_ci	{}
35262306a36Sopenharmony_ci};
35362306a36Sopenharmony_ciMODULE_DEVICE_TABLE(spi, ad5449_spi_ids);
35462306a36Sopenharmony_ci
35562306a36Sopenharmony_cistatic struct spi_driver ad5449_spi_driver = {
35662306a36Sopenharmony_ci	.driver = {
35762306a36Sopenharmony_ci		.name = "ad5449",
35862306a36Sopenharmony_ci	},
35962306a36Sopenharmony_ci	.probe = ad5449_spi_probe,
36062306a36Sopenharmony_ci	.remove = ad5449_spi_remove,
36162306a36Sopenharmony_ci	.id_table = ad5449_spi_ids,
36262306a36Sopenharmony_ci};
36362306a36Sopenharmony_cimodule_spi_driver(ad5449_spi_driver);
36462306a36Sopenharmony_ci
36562306a36Sopenharmony_ciMODULE_AUTHOR("Lars-Peter Clausen <lars@metafoo.de>");
36662306a36Sopenharmony_ciMODULE_DESCRIPTION("Analog Devices AD5449 and similar DACs");
36762306a36Sopenharmony_ciMODULE_LICENSE("GPL v2");
368