// SPDX-License-Identifier: GPL-2.0
/*
 * Driver for Linear Technology LTC1665/LTC1660, 8 channels DAC
 *
 * Copyright (C) 2018 Marcus Folkesson <marcus.folkesson@gmail.com>
 */
#include <linux/bitops.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/init.h>
#include <linux/module.h>
#include <linux/regulator/consumer.h>
#include <linux/regmap.h>
#include <linux/spi/spi.h>

#define LTC1660_REG_WAKE	0x0
#define LTC1660_REG_DAC_A	0x1
#define LTC1660_REG_DAC_B	0x2
#define LTC1660_REG_DAC_C	0x3
#define LTC1660_REG_DAC_D	0x4
#define LTC1660_REG_DAC_E	0x5
#define LTC1660_REG_DAC_F	0x6
#define LTC1660_REG_DAC_G	0x7
#define LTC1660_REG_DAC_H	0x8
#define LTC1660_REG_SLEEP	0xe

#define LTC1660_NUM_CHANNELS	8

static const struct regmap_config ltc1660_regmap_config = {
	.reg_bits = 4,
	.val_bits = 12,
};

enum ltc1660_supported_device_ids {
	ID_LTC1660,
	ID_LTC1665,
};

struct ltc1660_priv {
	struct spi_device *spi;
	struct regmap *regmap;
	struct regulator *vref_reg;
	unsigned int value[LTC1660_NUM_CHANNELS];
	unsigned int vref_mv;
};

static int ltc1660_read_raw(struct iio_dev *indio_dev,
		struct iio_chan_spec const *chan,
		int *val,
		int *val2,
		long mask)
{
	struct ltc1660_priv *priv = iio_priv(indio_dev);

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		*val = priv->value[chan->channel];
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		*val = regulator_get_voltage(priv->vref_reg);
		if (*val < 0) {
			dev_err(&priv->spi->dev, "failed to read vref regulator: %d\n",
					*val);
			return *val;
		}

		/* Convert to mV */
		*val /= 1000;
		*val2 = chan->scan_type.realbits;
		return IIO_VAL_FRACTIONAL_LOG2;
	default:
		return -EINVAL;
	}
}

static int ltc1660_write_raw(struct iio_dev *indio_dev,
		struct iio_chan_spec const *chan,
		int val,
		int val2,
		long mask)
{
	struct ltc1660_priv *priv = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		if (val2 != 0)
			return -EINVAL;

		if (val < 0 || val > GENMASK(chan->scan_type.realbits - 1, 0))
			return -EINVAL;

		ret = regmap_write(priv->regmap, chan->channel,
					(val << chan->scan_type.shift));
		if (!ret)
			priv->value[chan->channel] = val;

		return ret;
	default:
		return -EINVAL;
	}
}

#define LTC1660_CHAN(chan, bits) {			\
	.type = IIO_VOLTAGE,				\
	.indexed = 1,					\
	.output = 1,					\
	.channel = chan,				\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),	\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),	\
	.scan_type = {					\
		.sign = 'u',				\
		.realbits = (bits),			\
		.storagebits = 16,			\
		.shift = 12 - (bits),			\
	},						\
}

#define  LTC1660_OCTAL_CHANNELS(bits) {			\
		LTC1660_CHAN(LTC1660_REG_DAC_A, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_B, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_C, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_D, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_E, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_F, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_G, bits),	\
		LTC1660_CHAN(LTC1660_REG_DAC_H, bits),	\
}

static const struct iio_chan_spec ltc1660_channels[][LTC1660_NUM_CHANNELS] = {
	[ID_LTC1660] = LTC1660_OCTAL_CHANNELS(10),
	[ID_LTC1665] = LTC1660_OCTAL_CHANNELS(8),
};

static const struct iio_info ltc1660_info = {
	.read_raw = &ltc1660_read_raw,
	.write_raw = &ltc1660_write_raw,
};

static int __maybe_unused ltc1660_suspend(struct device *dev)
{
	struct ltc1660_priv *priv = iio_priv(spi_get_drvdata(
						to_spi_device(dev)));
	return regmap_write(priv->regmap, LTC1660_REG_SLEEP, 0x00);
}

static int __maybe_unused ltc1660_resume(struct device *dev)
{
	struct ltc1660_priv *priv = iio_priv(spi_get_drvdata(
						to_spi_device(dev)));
	return regmap_write(priv->regmap, LTC1660_REG_WAKE, 0x00);
}
static SIMPLE_DEV_PM_OPS(ltc1660_pm_ops, ltc1660_suspend, ltc1660_resume);

static int ltc1660_probe(struct spi_device *spi)
{
	struct iio_dev *indio_dev;
	struct ltc1660_priv *priv;
	const struct spi_device_id *id = spi_get_device_id(spi);
	int ret;

	indio_dev = devm_iio_device_alloc(&spi->dev, sizeof(*priv));
	if (indio_dev == NULL)
		return -ENOMEM;

	priv = iio_priv(indio_dev);
	priv->regmap = devm_regmap_init_spi(spi, &ltc1660_regmap_config);
	if (IS_ERR(priv->regmap)) {
		dev_err(&spi->dev, "failed to register spi regmap %ld\n",
			PTR_ERR(priv->regmap));
		return PTR_ERR(priv->regmap);
	}

	priv->vref_reg = devm_regulator_get(&spi->dev, "vref");
	if (IS_ERR(priv->vref_reg)) {
		dev_err(&spi->dev, "vref regulator not specified\n");
		return PTR_ERR(priv->vref_reg);
	}

	ret = regulator_enable(priv->vref_reg);
	if (ret) {
		dev_err(&spi->dev, "failed to enable vref regulator: %d\n",
				ret);
		return ret;
	}

	priv->spi = spi;
	spi_set_drvdata(spi, indio_dev);
	indio_dev->dev.parent = &spi->dev;
	indio_dev->info = &ltc1660_info;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->channels = ltc1660_channels[id->driver_data];
	indio_dev->num_channels = LTC1660_NUM_CHANNELS;
	indio_dev->name = id->name;

	ret = iio_device_register(indio_dev);
	if (ret) {
		dev_err(&spi->dev, "failed to register iio device: %d\n",
				ret);
		goto error_disable_reg;
	}

	return 0;

error_disable_reg:
	regulator_disable(priv->vref_reg);

	return ret;
}

static int ltc1660_remove(struct spi_device *spi)
{
	struct iio_dev *indio_dev = spi_get_drvdata(spi);
	struct ltc1660_priv *priv = iio_priv(indio_dev);

	iio_device_unregister(indio_dev);
	regulator_disable(priv->vref_reg);

	return 0;
}

static const struct of_device_id ltc1660_dt_ids[] = {
	{ .compatible = "lltc,ltc1660", .data = (void *)ID_LTC1660 },
	{ .compatible = "lltc,ltc1665", .data = (void *)ID_LTC1665 },
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(of, ltc1660_dt_ids);

static const struct spi_device_id ltc1660_id[] = {
	{"ltc1660", ID_LTC1660},
	{"ltc1665", ID_LTC1665},
	{ /* sentinel */ }
};
MODULE_DEVICE_TABLE(spi, ltc1660_id);

static struct spi_driver ltc1660_driver = {
	.driver = {
		.name = "ltc1660",
		.of_match_table = ltc1660_dt_ids,
		.pm = &ltc1660_pm_ops,
	},
	.probe	= ltc1660_probe,
	.remove = ltc1660_remove,
	.id_table = ltc1660_id,
};
module_spi_driver(ltc1660_driver);

MODULE_AUTHOR("Marcus Folkesson <marcus.folkesson@gmail.com>");
MODULE_DESCRIPTION("Linear Technology LTC1660/LTC1665 DAC");
MODULE_LICENSE("GPL v2");
