/*
 * ti-adc161s626.c - Texas Instruments ADC161S626 1-channel differential ADC
 *
 * ADC Devices Supported:
 *  adc141s626 - 14-bit ADC
 *  adc161s626 - 16-bit ADC
 *
 * Copyright (C) 2016 Matt Ranostay <mranostay@gmail.com>
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License as published by
 * the Free Software Foundation; either version 2 of the License, or
 * (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
 * GNU General Public License for more details.
 */

#include <linux/module.h>
#include <linux/init.h>
#include <linux/err.h>
#include <linux/spi/spi.h>
#include <linux/iio/iio.h>
#include <linux/iio/trigger.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <linux/regulator/consumer.h>

#define TI_ADC_DRV_NAME	"ti-adc161s626"

enum {
	TI_ADC141S626,
	TI_ADC161S626,
};

static const struct iio_chan_spec ti_adc141s626_channels[] = {
	{
		.type = IIO_VOLTAGE,
		.channel = 0,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
				      BIT(IIO_CHAN_INFO_SCALE) |
				      BIT(IIO_CHAN_INFO_OFFSET),
		.scan_index = 0,
		.scan_type = {
			.sign = 's',
			.realbits = 14,
			.storagebits = 16,
		},
	},
	IIO_CHAN_SOFT_TIMESTAMP(1),
};

static const struct iio_chan_spec ti_adc161s626_channels[] = {
	{
		.type = IIO_VOLTAGE,
		.channel = 0,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
				      BIT(IIO_CHAN_INFO_SCALE) |
				      BIT(IIO_CHAN_INFO_OFFSET),
		.scan_index = 0,
		.scan_type = {
			.sign = 's',
			.realbits = 16,
			.storagebits = 16,
		},
	},
	IIO_CHAN_SOFT_TIMESTAMP(1),
};

struct ti_adc_data {
	struct iio_dev *indio_dev;
	struct spi_device *spi;
	struct regulator *ref;

	u8 read_size;
	u8 shift;

	u8 buffer[16] ____cacheline_aligned;
};

static int ti_adc_read_measurement(struct ti_adc_data *data,
				   struct iio_chan_spec const *chan, int *val)
{
	int ret;

	switch (data->read_size) {
	case 2: {
		__be16 buf;

		ret = spi_read(data->spi, (void *) &buf, 2);
		if (ret)
			return ret;

		*val = be16_to_cpu(buf);
		break;
	}
	case 3: {
		__be32 buf;

		ret = spi_read(data->spi, (void *) &buf, 3);
		if (ret)
			return ret;

		*val = be32_to_cpu(buf) >> 8;
		break;
	}
	default:
		return -EINVAL;
	}

	*val = sign_extend32(*val >> data->shift, chan->scan_type.realbits - 1);

	return 0;
}

static irqreturn_t ti_adc_trigger_handler(int irq, void *private)
{
	struct iio_poll_func *pf = private;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct ti_adc_data *data = iio_priv(indio_dev);
	int ret;

	ret = ti_adc_read_measurement(data, &indio_dev->channels[0],
				     (int *) &data->buffer);
	if (!ret)
		iio_push_to_buffers_with_timestamp(indio_dev,
					data->buffer,
					iio_get_time_ns(indio_dev));

	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static int ti_adc_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	struct ti_adc_data *data = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = iio_device_claim_direct_mode(indio_dev);
		if (ret)
			return ret;

		ret = ti_adc_read_measurement(data, chan, val);
		iio_device_release_direct_mode(indio_dev);

		if (ret)
			return ret;

		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		ret = regulator_get_voltage(data->ref);
		if (ret < 0)
			return ret;

		*val = ret / 1000;
		*val2 = chan->scan_type.realbits;

		return IIO_VAL_FRACTIONAL_LOG2;
	case IIO_CHAN_INFO_OFFSET:
		*val = 1 << (chan->scan_type.realbits - 1);
		return IIO_VAL_INT;
	}

	return 0;
}

static const struct iio_info ti_adc_info = {
	.driver_module = THIS_MODULE,
	.read_raw = ti_adc_read_raw,
};

static int ti_adc_probe(struct spi_device *spi)
{
	struct iio_dev *indio_dev;
	struct ti_adc_data *data;
	int ret;

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

	indio_dev->info = &ti_adc_info;
	indio_dev->dev.parent = &spi->dev;
	indio_dev->dev.of_node = spi->dev.of_node;
	indio_dev->name = TI_ADC_DRV_NAME;
	indio_dev->modes = INDIO_DIRECT_MODE;
	spi_set_drvdata(spi, indio_dev);

	data = iio_priv(indio_dev);
	data->spi = spi;

	switch (spi_get_device_id(spi)->driver_data) {
	case TI_ADC141S626:
		indio_dev->channels = ti_adc141s626_channels;
		indio_dev->num_channels = ARRAY_SIZE(ti_adc141s626_channels);
		data->shift = 0;
		data->read_size = 2;
		break;
	case TI_ADC161S626:
		indio_dev->channels = ti_adc161s626_channels;
		indio_dev->num_channels = ARRAY_SIZE(ti_adc161s626_channels);
		data->shift = 6;
		data->read_size = 3;
		break;
	}

	data->ref = devm_regulator_get(&spi->dev, "vdda");
	if (!IS_ERR(data->ref)) {
		ret = regulator_enable(data->ref);
		if (ret < 0)
			return ret;
	}

	ret = iio_triggered_buffer_setup(indio_dev, NULL,
					 ti_adc_trigger_handler, NULL);
	if (ret)
		goto error_regulator_disable;

	ret = iio_device_register(indio_dev);
	if (ret)
		goto error_unreg_buffer;

	return 0;

error_unreg_buffer:
	iio_triggered_buffer_cleanup(indio_dev);

error_regulator_disable:
	regulator_disable(data->ref);

	return ret;
}

static int ti_adc_remove(struct spi_device *spi)
{
	struct iio_dev *indio_dev = spi_get_drvdata(spi);
	struct ti_adc_data *data = iio_priv(indio_dev);

	iio_device_unregister(indio_dev);
	iio_triggered_buffer_cleanup(indio_dev);
	regulator_disable(data->ref);

	return 0;
}

static const struct of_device_id ti_adc_dt_ids[] = {
	{ .compatible = "ti,adc141s626", },
	{ .compatible = "ti,adc161s626", },
	{}
};
MODULE_DEVICE_TABLE(of, ti_adc_dt_ids);

static const struct spi_device_id ti_adc_id[] = {
	{"adc141s626", TI_ADC141S626},
	{"adc161s626", TI_ADC161S626},
	{},
};
MODULE_DEVICE_TABLE(spi, ti_adc_id);

static struct spi_driver ti_adc_driver = {
	.driver = {
		.name	= TI_ADC_DRV_NAME,
		.of_match_table = of_match_ptr(ti_adc_dt_ids),
	},
	.probe		= ti_adc_probe,
	.remove		= ti_adc_remove,
	.id_table	= ti_adc_id,
};
module_spi_driver(ti_adc_driver);

MODULE_AUTHOR("Matt Ranostay <mranostay@gmail.com>");
MODULE_DESCRIPTION("Texas Instruments ADC1x1S 1-channel differential ADC");
MODULE_LICENSE("GPL");
