// SPDX-License-Identifier: GPL-2.0
/*
 * ADC driver for Basin Cove PMIC
 *
 * Copyright (C) 2012 Intel Corporation
 * Author: Bin Yang <bin.yang@intel.com>
 *
 * Rewritten for upstream by:
 *	 Vincent Pelletier <plr.vincent@gmail.com>
 *	 Andy Shevchenko <andriy.shevchenko@linux.intel.com>
 */

#include <linux/bitops.h>
#include <linux/completion.h>
#include <linux/interrupt.h>
#include <linux/mfd/intel_soc_pmic.h>
#include <linux/mfd/intel_soc_pmic_mrfld.h>
#include <linux/mod_devicetable.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/platform_device.h>
#include <linux/regmap.h>

#include <linux/iio/driver.h>
#include <linux/iio/iio.h>
#include <linux/iio/machine.h>

#include <asm/unaligned.h>

#define BCOVE_GPADCREQ			0xDC
#define BCOVE_GPADCREQ_BUSY		BIT(0)
#define BCOVE_GPADCREQ_IRQEN		BIT(1)

#define BCOVE_ADCIRQ_ALL (		\
	BCOVE_ADCIRQ_BATTEMP |		\
	BCOVE_ADCIRQ_SYSTEMP |		\
	BCOVE_ADCIRQ_BATTID |		\
	BCOVE_ADCIRQ_VIBATT |		\
	BCOVE_ADCIRQ_CCTICK)

#define BCOVE_ADC_TIMEOUT		msecs_to_jiffies(1000)

static const u8 mrfld_adc_requests[] = {
	BCOVE_ADCIRQ_VIBATT,
	BCOVE_ADCIRQ_BATTID,
	BCOVE_ADCIRQ_VIBATT,
	BCOVE_ADCIRQ_SYSTEMP,
	BCOVE_ADCIRQ_BATTEMP,
	BCOVE_ADCIRQ_BATTEMP,
	BCOVE_ADCIRQ_SYSTEMP,
	BCOVE_ADCIRQ_SYSTEMP,
	BCOVE_ADCIRQ_SYSTEMP,
};

struct mrfld_adc {
	struct regmap *regmap;
	struct completion completion;
	/* Lock to protect the IPC transfers */
	struct mutex lock;
};

static irqreturn_t mrfld_adc_thread_isr(int irq, void *data)
{
	struct iio_dev *indio_dev = data;
	struct mrfld_adc *adc = iio_priv(indio_dev);

	complete(&adc->completion);
	return IRQ_HANDLED;
}

static int mrfld_adc_single_conv(struct iio_dev *indio_dev,
				 struct iio_chan_spec const *chan,
				 int *result)
{
	struct mrfld_adc *adc = iio_priv(indio_dev);
	struct regmap *regmap = adc->regmap;
	unsigned int req;
	long time_left;
	__be16 value;
	int ret;

	reinit_completion(&adc->completion);

	regmap_clear_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL);
	regmap_clear_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC);

	ret = regmap_read_poll_timeout(regmap, BCOVE_GPADCREQ, req,
				       !(req & BCOVE_GPADCREQ_BUSY),
				       2000, 1000000);
	if (ret)
		goto done;

	req = mrfld_adc_requests[chan->channel];
	ret = regmap_write(regmap, BCOVE_GPADCREQ, BCOVE_GPADCREQ_IRQEN | req);
	if (ret)
		goto done;

	time_left = wait_for_completion_interruptible_timeout(&adc->completion,
							      BCOVE_ADC_TIMEOUT);
	if (time_left < 0) {
		ret = time_left;
		goto done;
	}
	if (time_left == 0) {
		ret = -ETIMEDOUT;
		goto done;
	}

	ret = regmap_bulk_read(regmap, chan->address, &value, sizeof(value));
	if (ret)
		goto done;

	*result = be16_to_cpu(value);
	ret = IIO_VAL_INT;

done:
	regmap_update_bits(regmap, BCOVE_MIRQLVL1, BCOVE_LVL1_ADC, 0xff);
	regmap_update_bits(regmap, BCOVE_MADCIRQ, BCOVE_ADCIRQ_ALL, 0xff);

	return ret;
}

static int mrfld_adc_read_raw(struct iio_dev *indio_dev,
			      struct iio_chan_spec const *chan,
			      int *val, int *val2, long mask)
{
	struct mrfld_adc *adc = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		mutex_lock(&adc->lock);
		ret = mrfld_adc_single_conv(indio_dev, chan, val);
		mutex_unlock(&adc->lock);
		return ret;
	default:
		return -EINVAL;
	}
}

static const struct iio_info mrfld_adc_iio_info = {
	.read_raw = &mrfld_adc_read_raw,
};

#define BCOVE_ADC_CHANNEL(_type, _channel, _datasheet_name, _address)	\
	{								\
		.indexed = 1,						\
		.type = _type,						\
		.channel = _channel,					\
		.address = _address,					\
		.datasheet_name = _datasheet_name,			\
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),		\
	}

static const struct iio_chan_spec mrfld_adc_channels[] = {
	BCOVE_ADC_CHANNEL(IIO_VOLTAGE,    0, "CH0", 0xE9),
	BCOVE_ADC_CHANNEL(IIO_RESISTANCE, 1, "CH1", 0xEB),
	BCOVE_ADC_CHANNEL(IIO_CURRENT,    2, "CH2", 0xED),
	BCOVE_ADC_CHANNEL(IIO_TEMP,       3, "CH3", 0xCC),
	BCOVE_ADC_CHANNEL(IIO_TEMP,       4, "CH4", 0xC8),
	BCOVE_ADC_CHANNEL(IIO_TEMP,       5, "CH5", 0xCA),
	BCOVE_ADC_CHANNEL(IIO_TEMP,       6, "CH6", 0xC2),
	BCOVE_ADC_CHANNEL(IIO_TEMP,       7, "CH7", 0xC4),
	BCOVE_ADC_CHANNEL(IIO_TEMP,       8, "CH8", 0xC6),
};

static struct iio_map iio_maps[] = {
	IIO_MAP("CH0", "bcove-battery", "VBATRSLT"),
	IIO_MAP("CH1", "bcove-battery", "BATTID"),
	IIO_MAP("CH2", "bcove-battery", "IBATRSLT"),
	IIO_MAP("CH3", "bcove-temp",    "PMICTEMP"),
	IIO_MAP("CH4", "bcove-temp",    "BATTEMP0"),
	IIO_MAP("CH5", "bcove-temp",    "BATTEMP1"),
	IIO_MAP("CH6", "bcove-temp",    "SYSTEMP0"),
	IIO_MAP("CH7", "bcove-temp",    "SYSTEMP1"),
	IIO_MAP("CH8", "bcove-temp",    "SYSTEMP2"),
	{}
};

static int mrfld_adc_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct intel_soc_pmic *pmic = dev_get_drvdata(dev->parent);
	struct iio_dev *indio_dev;
	struct mrfld_adc *adc;
	int irq;
	int ret;

	indio_dev = devm_iio_device_alloc(dev, sizeof(struct mrfld_adc));
	if (!indio_dev)
		return -ENOMEM;

	adc = iio_priv(indio_dev);

	mutex_init(&adc->lock);
	init_completion(&adc->completion);
	adc->regmap = pmic->regmap;

	irq = platform_get_irq(pdev, 0);
	if (irq < 0)
		return irq;

	ret = devm_request_threaded_irq(dev, irq, NULL, mrfld_adc_thread_isr,
					IRQF_ONESHOT | IRQF_SHARED, pdev->name,
					indio_dev);
	if (ret)
		return ret;

	indio_dev->name = pdev->name;

	indio_dev->channels = mrfld_adc_channels;
	indio_dev->num_channels = ARRAY_SIZE(mrfld_adc_channels);
	indio_dev->info = &mrfld_adc_iio_info;
	indio_dev->modes = INDIO_DIRECT_MODE;

	ret = devm_iio_map_array_register(dev, indio_dev, iio_maps);
	if (ret)
		return ret;

	return devm_iio_device_register(dev, indio_dev);
}

static const struct platform_device_id mrfld_adc_id_table[] = {
	{ .name = "mrfld_bcove_adc" },
	{}
};
MODULE_DEVICE_TABLE(platform, mrfld_adc_id_table);

static struct platform_driver mrfld_adc_driver = {
	.driver = {
		.name = "mrfld_bcove_adc",
	},
	.probe = mrfld_adc_probe,
	.id_table = mrfld_adc_id_table,
};
module_platform_driver(mrfld_adc_driver);

MODULE_AUTHOR("Bin Yang <bin.yang@intel.com>");
MODULE_AUTHOR("Vincent Pelletier <plr.vincent@gmail.com>");
MODULE_AUTHOR("Andy Shevchenko <andriy.shevchenko@linux.intel.com>");
MODULE_DESCRIPTION("ADC driver for Basin Cove PMIC");
MODULE_LICENSE("GPL v2");
