/*
 * Copyright (c) 2016 Marek Vasut <marex@denx.de>
 *
 * Driver for Hope RF HP03 digital temperature and pressure sensor.
 *
 * This program is free software; you can redistribute it and/or modify
 * it under the terms of the GNU General Public License version 2 as
 * published by the Free Software Foundation.
 */

#define pr_fmt(fmt) "hp03: " fmt

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/gpio/consumer.h>
#include <linux/i2c.h>
#include <linux/regmap.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>

/*
 * The HP03 sensor occupies two fixed I2C addresses:
 *  0x50 ... read-only EEPROM with calibration data
 *  0x77 ... read-write ADC for pressure and temperature
 */
#define HP03_EEPROM_ADDR		0x50
#define HP03_ADC_ADDR			0x77

#define HP03_EEPROM_CX_OFFSET		0x10
#define HP03_EEPROM_AB_OFFSET		0x1e
#define HP03_EEPROM_CD_OFFSET		0x20

#define HP03_ADC_WRITE_REG		0xff
#define HP03_ADC_READ_REG		0xfd
#define HP03_ADC_READ_PRESSURE		0xf0	/* D1 in datasheet */
#define HP03_ADC_READ_TEMP		0xe8	/* D2 in datasheet */

struct hp03_priv {
	struct i2c_client	*client;
	struct mutex		lock;
	struct gpio_desc	*xclr_gpio;

	struct i2c_client	*eeprom_client;
	struct regmap		*eeprom_regmap;

	s32			pressure;	/* kPa */
	s32			temp;		/* Deg. C */
};

static const struct iio_chan_spec hp03_channels[] = {
	{
		.type = IIO_PRESSURE,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
	},
	{
		.type = IIO_TEMP,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
		.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE),
	},
};

static bool hp03_is_writeable_reg(struct device *dev, unsigned int reg)
{
	return false;
}

static bool hp03_is_volatile_reg(struct device *dev, unsigned int reg)
{
	return false;
}

static const struct regmap_config hp03_regmap_config = {
	.reg_bits	= 8,
	.val_bits	= 8,

	.max_register	= HP03_EEPROM_CD_OFFSET + 1,
	.cache_type	= REGCACHE_RBTREE,

	.writeable_reg	= hp03_is_writeable_reg,
	.volatile_reg	= hp03_is_volatile_reg,
};

static int hp03_get_temp_pressure(struct hp03_priv *priv, const u8 reg)
{
	int ret;

	ret = i2c_smbus_write_byte_data(priv->client, HP03_ADC_WRITE_REG, reg);
	if (ret < 0)
		return ret;

	msleep(50);	/* Wait for conversion to finish */

	return i2c_smbus_read_word_data(priv->client, HP03_ADC_READ_REG);
}

static int hp03_update_temp_pressure(struct hp03_priv *priv)
{
	struct device *dev = &priv->client->dev;
	u8 coefs[18];
	u16 cx_val[7];
	int ab_val, d1_val, d2_val, diff_val, dut, off, sens, x;
	int i, ret;

	/* Sample coefficients from EEPROM */
	ret = regmap_bulk_read(priv->eeprom_regmap, HP03_EEPROM_CX_OFFSET,
			       coefs, sizeof(coefs));
	if (ret < 0) {
		dev_err(dev, "Failed to read EEPROM (reg=%02x)\n",
			HP03_EEPROM_CX_OFFSET);
		return ret;
	}

	/* Sample Temperature and Pressure */
	gpiod_set_value_cansleep(priv->xclr_gpio, 1);

	ret = hp03_get_temp_pressure(priv, HP03_ADC_READ_PRESSURE);
	if (ret < 0) {
		dev_err(dev, "Failed to read pressure\n");
		goto err_adc;
	}
	d1_val = ret;

	ret = hp03_get_temp_pressure(priv, HP03_ADC_READ_TEMP);
	if (ret < 0) {
		dev_err(dev, "Failed to read temperature\n");
		goto err_adc;
	}
	d2_val = ret;

	gpiod_set_value_cansleep(priv->xclr_gpio, 0);

	/* The Cx coefficients and Temp/Pressure values are MSB first. */
	for (i = 0; i < 7; i++)
		cx_val[i] = (coefs[2 * i] << 8) | (coefs[(2 * i) + 1] << 0);
	d1_val = ((d1_val >> 8) & 0xff) | ((d1_val & 0xff) << 8);
	d2_val = ((d2_val >> 8) & 0xff) | ((d2_val & 0xff) << 8);

	/* Coefficient voodoo from the HP03 datasheet. */
	if (d2_val >= cx_val[4])
		ab_val = coefs[14];	/* A-value */
	else
		ab_val = coefs[15];	/* B-value */

	diff_val = d2_val - cx_val[4];
	dut = (ab_val * (diff_val >> 7) * (diff_val >> 7)) >> coefs[16];
	dut = diff_val - dut;

	off = (cx_val[1] + (((cx_val[3] - 1024) * dut) >> 14)) * 4;
	sens = cx_val[0] + ((cx_val[2] * dut) >> 10);
	x = ((sens * (d1_val - 7168)) >> 14) - off;

	priv->pressure = ((x * 100) >> 5) + (cx_val[6] * 10);
	priv->temp = 250 + ((dut * cx_val[5]) >> 16) - (dut >> coefs[17]);

	return 0;

err_adc:
	gpiod_set_value_cansleep(priv->xclr_gpio, 0);
	return ret;
}

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

	mutex_lock(&priv->lock);
	ret = hp03_update_temp_pressure(priv);
	mutex_unlock(&priv->lock);

	if (ret)
		return ret;

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		switch (chan->type) {
		case IIO_PRESSURE:
			*val = priv->pressure;
			return IIO_VAL_INT;
		case IIO_TEMP:
			*val = priv->temp;
			return IIO_VAL_INT;
		default:
			return -EINVAL;
		}
		break;
	case IIO_CHAN_INFO_SCALE:
		switch (chan->type) {
		case IIO_PRESSURE:
			*val = 0;
			*val2 = 1000;
			return IIO_VAL_INT_PLUS_MICRO;
		case IIO_TEMP:
			*val = 10;
			return IIO_VAL_INT;
		default:
			return -EINVAL;
		}
		break;
	default:
		return -EINVAL;
	}

	return -EINVAL;
}

static const struct iio_info hp03_info = {
	.read_raw	= &hp03_read_raw,
};

static int hp03_probe(struct i2c_client *client,
		      const struct i2c_device_id *id)
{
	struct device *dev = &client->dev;
	struct iio_dev *indio_dev;
	struct hp03_priv *priv;
	int ret;

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

	priv = iio_priv(indio_dev);
	priv->client = client;
	mutex_init(&priv->lock);

	indio_dev->dev.parent = dev;
	indio_dev->name = id->name;
	indio_dev->channels = hp03_channels;
	indio_dev->num_channels = ARRAY_SIZE(hp03_channels);
	indio_dev->info = &hp03_info;
	indio_dev->modes = INDIO_DIRECT_MODE;

	priv->xclr_gpio = devm_gpiod_get_index(dev, "xclr", 0, GPIOD_OUT_HIGH);
	if (IS_ERR(priv->xclr_gpio)) {
		dev_err(dev, "Failed to claim XCLR GPIO\n");
		ret = PTR_ERR(priv->xclr_gpio);
		return ret;
	}

	/*
	 * Allocate another device for the on-sensor EEPROM,
	 * which has it's dedicated I2C address and contains
	 * the calibration constants for the sensor.
	 */
	priv->eeprom_client = i2c_new_dummy(client->adapter, HP03_EEPROM_ADDR);
	if (!priv->eeprom_client) {
		dev_err(dev, "New EEPROM I2C device failed\n");
		return -ENODEV;
	}

	priv->eeprom_regmap = regmap_init_i2c(priv->eeprom_client,
					      &hp03_regmap_config);
	if (IS_ERR(priv->eeprom_regmap)) {
		dev_err(dev, "Failed to allocate EEPROM regmap\n");
		ret = PTR_ERR(priv->eeprom_regmap);
		goto err_cleanup_eeprom_client;
	}

	ret = iio_device_register(indio_dev);
	if (ret) {
		dev_err(dev, "Failed to register IIO device\n");
		goto err_cleanup_eeprom_regmap;
	}

	i2c_set_clientdata(client, indio_dev);

	return 0;

err_cleanup_eeprom_regmap:
	regmap_exit(priv->eeprom_regmap);

err_cleanup_eeprom_client:
	i2c_unregister_device(priv->eeprom_client);
	return ret;
}

static int hp03_remove(struct i2c_client *client)
{
	struct iio_dev *indio_dev = i2c_get_clientdata(client);
	struct hp03_priv *priv = iio_priv(indio_dev);

	iio_device_unregister(indio_dev);
	regmap_exit(priv->eeprom_regmap);
	i2c_unregister_device(priv->eeprom_client);

	return 0;
}

static const struct i2c_device_id hp03_id[] = {
	{ "hp03", 0 },
	{ },
};
MODULE_DEVICE_TABLE(i2c, hp03_id);

static const struct of_device_id hp03_of_match[] = {
	{ .compatible = "hoperf,hp03" },
	{ },
};
MODULE_DEVICE_TABLE(of, hp03_of_match);

static struct i2c_driver hp03_driver = {
	.driver = {
		.name	= "hp03",
		.of_match_table = hp03_of_match,
	},
	.probe		= hp03_probe,
	.remove		= hp03_remove,
	.id_table	= hp03_id,
};
module_i2c_driver(hp03_driver);

MODULE_AUTHOR("Marek Vasut <marex@denx.de>");
MODULE_DESCRIPTION("Driver for Hope RF HP03 pressure and temperature sensor");
MODULE_LICENSE("GPL v2");
