// SPDX-License-Identifier: GPL-2.0-or-later
/*
 * Copyright (C) 2023 Anshul Dalal <anshulusr@gmail.com>
 *
 * Driver for Aosong AGS02MA
 *
 * Datasheet:
 *   https://asairsensors.com/wp-content/uploads/2021/09/AGS02MA.pdf
 * Product Page:
 *   http://www.aosong.com/m/en/products-33.html
 */

#include <linux/crc8.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/module.h>

#include <linux/iio/iio.h>

#define AGS02MA_TVOC_READ_REG		   0x00
#define AGS02MA_VERSION_REG		   0x11

#define AGS02MA_VERSION_PROCESSING_DELAY   30
#define AGS02MA_TVOC_READ_PROCESSING_DELAY 1500

#define AGS02MA_CRC8_INIT		   0xff
#define AGS02MA_CRC8_POLYNOMIAL		   0x31

DECLARE_CRC8_TABLE(ags02ma_crc8_table);

struct ags02ma_data {
	struct i2c_client *client;
};

struct ags02ma_reading {
	__be32 data;
	u8 crc;
} __packed;

static int ags02ma_register_read(struct i2c_client *client, u8 reg, u16 delay,
				 u32 *val)
{
	int ret;
	u8 crc;
	struct ags02ma_reading read_buffer;

	ret = i2c_master_send(client, &reg, sizeof(reg));
	if (ret < 0) {
		dev_err(&client->dev,
			"Failed to send data to register 0x%x: %d", reg, ret);
		return ret;
	}

	/* Processing Delay, Check Table 7.7 in the datasheet */
	msleep_interruptible(delay);

	ret = i2c_master_recv(client, (u8 *)&read_buffer, sizeof(read_buffer));
	if (ret < 0) {
		dev_err(&client->dev,
			"Failed to receive from register 0x%x: %d", reg, ret);
		return ret;
	}

	crc = crc8(ags02ma_crc8_table, (u8 *)&read_buffer.data,
		   sizeof(read_buffer.data), AGS02MA_CRC8_INIT);
	if (crc != read_buffer.crc) {
		dev_err(&client->dev, "CRC error\n");
		return -EIO;
	}

	*val = be32_to_cpu(read_buffer.data);
	return 0;
}

static int ags02ma_read_raw(struct iio_dev *iio_device,
			    struct iio_chan_spec const *chan, int *val,
			    int *val2, long mask)
{
	int ret;
	struct ags02ma_data *data = iio_priv(iio_device);

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = ags02ma_register_read(data->client, AGS02MA_TVOC_READ_REG,
					    AGS02MA_TVOC_READ_PROCESSING_DELAY,
					    val);
		if (ret < 0)
			return ret;
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		/* The sensor reads data as ppb */
		*val = 0;
		*val2 = 100;
		return IIO_VAL_INT_PLUS_NANO;
	default:
		return -EINVAL;
	}
}

static const struct iio_info ags02ma_info = {
	.read_raw = ags02ma_read_raw,
};

static const struct iio_chan_spec ags02ma_channel = {
	.type = IIO_CONCENTRATION,
	.channel2 = IIO_MOD_VOC,
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW) |
		BIT(IIO_CHAN_INFO_SCALE),
};

static int ags02ma_probe(struct i2c_client *client)
{
	int ret;
	struct ags02ma_data *data;
	struct iio_dev *indio_dev;
	u32 version;

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

	crc8_populate_msb(ags02ma_crc8_table, AGS02MA_CRC8_POLYNOMIAL);

	ret = ags02ma_register_read(client, AGS02MA_VERSION_REG,
				    AGS02MA_VERSION_PROCESSING_DELAY, &version);
	if (ret < 0)
		return dev_err_probe(&client->dev, ret,
			      "Failed to read device version\n");
	dev_dbg(&client->dev, "Aosong AGS02MA, Version: 0x%x", version);

	data = iio_priv(indio_dev);
	data->client = client;
	indio_dev->info = &ags02ma_info;
	indio_dev->channels = &ags02ma_channel;
	indio_dev->num_channels = 1;
	indio_dev->name = "ags02ma";

	return devm_iio_device_register(&client->dev, indio_dev);
}

static const struct i2c_device_id ags02ma_id_table[] = {
	{ "ags02ma" },
	{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(i2c, ags02ma_id_table);

static const struct of_device_id ags02ma_of_table[] = {
	{ .compatible = "aosong,ags02ma" },
	{ /* Sentinel */ }
};
MODULE_DEVICE_TABLE(of, ags02ma_of_table);

static struct i2c_driver ags02ma_driver = {
	.driver = {
		.name = "ags02ma",
		.of_match_table = ags02ma_of_table,
	},
	.id_table = ags02ma_id_table,
	.probe = ags02ma_probe,
};
module_i2c_driver(ags02ma_driver);

MODULE_AUTHOR("Anshul Dalal <anshulusr@gmail.com>");
MODULE_DESCRIPTION("Aosong AGS02MA TVOC Driver");
MODULE_LICENSE("GPL");
