// SPDX-License-Identifier: GPL-2.0-only
/*
 * Generic ADC thermal driver
 *
 * Copyright (C) 2016 NVIDIA CORPORATION. All rights reserved.
 *
 * Author: Laxman Dewangan <ldewangan@nvidia.com>
 */
#include <linux/iio/consumer.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>
#include <linux/module.h>
#include <linux/platform_device.h>
#include <linux/slab.h>
#include <linux/thermal.h>

#include "thermal_hwmon.h"

struct gadc_thermal_info {
	struct device *dev;
	struct thermal_zone_device *tz_dev;
	struct iio_channel *channel;
	s32 *lookup_table;
	int nlookup_table;
};

static int gadc_thermal_adc_to_temp(struct gadc_thermal_info *gti, int val)
{
	int temp, temp_hi, temp_lo, adc_hi, adc_lo;
	int i;

	if (!gti->lookup_table)
		return val;

	for (i = 0; i < gti->nlookup_table; i++) {
		if (val >= gti->lookup_table[2 * i + 1])
			break;
	}

	if (i == 0) {
		temp = gti->lookup_table[0];
	} else if (i >= gti->nlookup_table) {
		temp = gti->lookup_table[2 * (gti->nlookup_table - 1)];
	} else {
		adc_hi = gti->lookup_table[2 * i - 1];
		adc_lo = gti->lookup_table[2 * i + 1];

		temp_hi = gti->lookup_table[2 * i - 2];
		temp_lo = gti->lookup_table[2 * i];

		temp = temp_hi + mult_frac(temp_lo - temp_hi, val - adc_hi,
					   adc_lo - adc_hi);
	}

	return temp;
}

static int gadc_thermal_get_temp(struct thermal_zone_device *tz, int *temp)
{
	struct gadc_thermal_info *gti = thermal_zone_device_priv(tz);
	int val;
	int ret;

	ret = iio_read_channel_processed(gti->channel, &val);
	if (ret < 0)
		return ret;

	*temp = gadc_thermal_adc_to_temp(gti, val);

	return 0;
}

static const struct thermal_zone_device_ops gadc_thermal_ops = {
	.get_temp = gadc_thermal_get_temp,
};

static const struct iio_chan_spec gadc_thermal_iio_channels[] = {
	{
		.type = IIO_TEMP,
		.info_mask_separate = BIT(IIO_CHAN_INFO_PROCESSED),
	}
};

static int gadc_thermal_read_raw(struct iio_dev *indio_dev,
				 struct iio_chan_spec const *chan,
				 int *val, int *val2, long mask)
{
	struct gadc_thermal_info *gtinfo = iio_priv(indio_dev);
	int ret;

	switch (mask) {
	case IIO_CHAN_INFO_PROCESSED:
		ret = gadc_thermal_get_temp(gtinfo->tz_dev, val);
		if (ret)
			return ret;

		return IIO_VAL_INT;

	default:
		return -EINVAL;
	}
}

static const struct iio_info gadc_thermal_iio_info = {
	.read_raw = gadc_thermal_read_raw,
};

static int gadc_iio_register(struct device *dev, struct gadc_thermal_info *gti)
{
	struct gadc_thermal_info *gtinfo;
	struct iio_dev *indio_dev;

	indio_dev = devm_iio_device_alloc(dev, sizeof(*gtinfo));
	if (!indio_dev)
		return -ENOMEM;

	gtinfo = iio_priv(indio_dev);
	memcpy(gtinfo, gti, sizeof(*gtinfo));

	indio_dev->name = dev_name(dev);
	indio_dev->info = &gadc_thermal_iio_info;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->channels = gadc_thermal_iio_channels;
	indio_dev->num_channels = ARRAY_SIZE(gadc_thermal_iio_channels);

	return devm_iio_device_register(dev, indio_dev);
}

static int gadc_thermal_read_linear_lookup_table(struct device *dev,
						 struct gadc_thermal_info *gti)
{
	struct device_node *np = dev->of_node;
	enum iio_chan_type chan_type;
	int ntable;
	int ret;

	ntable = of_property_count_elems_of_size(np, "temperature-lookup-table",
						 sizeof(u32));
	if (ntable <= 0) {
		ret = iio_get_channel_type(gti->channel, &chan_type);
		if (ret || chan_type != IIO_TEMP)
			dev_notice(dev,
				   "no lookup table, assuming DAC channel returns milliCelcius\n");
		return 0;
	}

	if (ntable % 2) {
		dev_err(dev, "Pair of temperature vs ADC read value missing\n");
		return -EINVAL;
	}

	gti->lookup_table = devm_kcalloc(dev,
					 ntable, sizeof(*gti->lookup_table),
					 GFP_KERNEL);
	if (!gti->lookup_table)
		return -ENOMEM;

	ret = of_property_read_u32_array(np, "temperature-lookup-table",
					 (u32 *)gti->lookup_table, ntable);
	if (ret < 0) {
		dev_err(dev, "Failed to read temperature lookup table: %d\n",
			ret);
		return ret;
	}

	gti->nlookup_table = ntable / 2;

	return 0;
}

static int gadc_thermal_probe(struct platform_device *pdev)
{
	struct device *dev = &pdev->dev;
	struct gadc_thermal_info *gti;
	int ret;

	if (!dev->of_node) {
		dev_err(dev, "Only DT based supported\n");
		return -ENODEV;
	}

	gti = devm_kzalloc(dev, sizeof(*gti), GFP_KERNEL);
	if (!gti)
		return -ENOMEM;

	gti->channel = devm_iio_channel_get(dev, "sensor-channel");
	if (IS_ERR(gti->channel))
		return dev_err_probe(dev, PTR_ERR(gti->channel), "IIO channel not found\n");

	ret = gadc_thermal_read_linear_lookup_table(dev, gti);
	if (ret < 0)
		return ret;

	gti->dev = dev;

	gti->tz_dev = devm_thermal_of_zone_register(dev, 0, gti,
						    &gadc_thermal_ops);
	if (IS_ERR(gti->tz_dev)) {
		ret = PTR_ERR(gti->tz_dev);
		if (ret != -EPROBE_DEFER)
			dev_err(dev,
				"Thermal zone sensor register failed: %d\n",
				ret);
		return ret;
	}

	devm_thermal_add_hwmon_sysfs(dev, gti->tz_dev);

	return gadc_iio_register(&pdev->dev, gti);
}

static const struct of_device_id of_adc_thermal_match[] = {
	{ .compatible = "generic-adc-thermal", },
	{},
};
MODULE_DEVICE_TABLE(of, of_adc_thermal_match);

static struct platform_driver gadc_thermal_driver = {
	.driver = {
		.name = "generic-adc-thermal",
		.of_match_table = of_adc_thermal_match,
	},
	.probe = gadc_thermal_probe,
};

module_platform_driver(gadc_thermal_driver);

MODULE_AUTHOR("Laxman Dewangan <ldewangan@nvidia.com>");
MODULE_DESCRIPTION("Generic ADC thermal driver using IIO framework with DT");
MODULE_LICENSE("GPL v2");
