// SPDX-License-Identifier: GPL-2.0
/*
 * All Sensors DLH series low voltage digital pressure sensors
 *
 * Copyright (c) 2019 AVL DiTEST GmbH
 *   Tomislav Denis <tomislav.denis@avl.com>
 *
 * Datasheet: http://www.allsensors.com/cad/DS-0355_Rev_B.PDF
 */

#include <linux/module.h>
#include <linux/delay.h>
#include <linux/i2c.h>
#include <linux/iio/iio.h>
#include <linux/iio/buffer.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>
#include <asm/unaligned.h>

/* Commands */
#define DLH_START_SINGLE    0xAA

/* Status bits */
#define DLH_STATUS_OK       0x40

/* DLH  data format */
#define DLH_NUM_READ_BYTES  7
#define DLH_NUM_DATA_BYTES  3
#define DLH_NUM_PR_BITS     24
#define DLH_NUM_TEMP_BITS   24

/* DLH  timings */
#define DLH_SINGLE_DUT_MS   5

enum dhl_ids {
	dlhl60d,
	dlhl60g,
};

struct dlh_info {
	u8 osdig;           /* digital offset factor */
	unsigned int fss;   /* full scale span (inch H2O) */
};

struct dlh_state {
	struct i2c_client *client;
	struct dlh_info info;
	bool use_interrupt;
	struct completion completion;
	u8 rx_buf[DLH_NUM_READ_BYTES] ____cacheline_aligned;
};

static struct dlh_info dlh_info_tbl[] = {
	[dlhl60d] = {
		.osdig = 2,
		.fss = 120,
	},
	[dlhl60g] = {
		.osdig = 10,
		.fss = 60,
	},
};


static int dlh_cmd_start_single(struct dlh_state *st)
{
	int ret;

	ret = i2c_smbus_write_byte(st->client, DLH_START_SINGLE);
	if (ret)
		dev_err(&st->client->dev,
			"%s: I2C write byte failed\n", __func__);

	return ret;
}

static int dlh_cmd_read_data(struct dlh_state *st)
{
	int ret;

	ret = i2c_master_recv(st->client, st->rx_buf, DLH_NUM_READ_BYTES);
	if (ret < 0) {
		dev_err(&st->client->dev,
			"%s: I2C read block failed\n", __func__);
		return ret;
	}

	if (st->rx_buf[0] != DLH_STATUS_OK) {
		dev_err(&st->client->dev,
			"%s: invalid status 0x%02x\n", __func__, st->rx_buf[0]);
		return -EBUSY;
	}

	return 0;
}

static int dlh_start_capture_and_read(struct dlh_state *st)
{
	int ret;

	if (st->use_interrupt)
		reinit_completion(&st->completion);

	ret = dlh_cmd_start_single(st);
	if (ret)
		return ret;

	if (st->use_interrupt) {
		ret = wait_for_completion_timeout(&st->completion,
			msecs_to_jiffies(DLH_SINGLE_DUT_MS));
		if (!ret) {
			dev_err(&st->client->dev,
				"%s: conversion timed out\n", __func__);
			return -ETIMEDOUT;
		}
	} else {
		mdelay(DLH_SINGLE_DUT_MS);
	}

	return dlh_cmd_read_data(st);
}

static int dlh_read_direct(struct dlh_state *st,
	unsigned int *pressure, unsigned int *temperature)
{
	int ret;

	ret = dlh_start_capture_and_read(st);
	if (ret)
		return ret;

	*pressure = get_unaligned_be32(&st->rx_buf[1]) >> 8;
	*temperature = get_unaligned_be32(&st->rx_buf[3]) &
		GENMASK(DLH_NUM_TEMP_BITS - 1, 0);

	return 0;
}

static int dlh_read_raw(struct iio_dev *indio_dev,
	struct iio_chan_spec const *channel, int *value,
	int *value2, long mask)
{
	struct dlh_state *st = iio_priv(indio_dev);
	unsigned int pressure, temperature;
	int ret;
	s64 tmp;
	s32 rem;

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

		ret = dlh_read_direct(st, &pressure, &temperature);
		iio_device_release_direct_mode(indio_dev);
		if (ret)
			return ret;

		switch (channel->type) {
		case IIO_PRESSURE:
			*value = pressure;
			return IIO_VAL_INT;

		case IIO_TEMP:
			*value = temperature;
			return IIO_VAL_INT;

		default:
			return -EINVAL;
		}
	case IIO_CHAN_INFO_SCALE:
		switch (channel->type) {
		case IIO_PRESSURE:
			tmp = div_s64(125LL * st->info.fss * 24909 * 100,
				1 << DLH_NUM_PR_BITS);
			tmp = div_s64_rem(tmp, 1000000000LL, &rem);
			*value = tmp;
			*value2 = rem;
			return IIO_VAL_INT_PLUS_NANO;

		case IIO_TEMP:
			*value = 125 * 1000;
			*value2 = DLH_NUM_TEMP_BITS;
			return IIO_VAL_FRACTIONAL_LOG2;

		default:
			return -EINVAL;
		}
	case IIO_CHAN_INFO_OFFSET:
		switch (channel->type) {
		case IIO_PRESSURE:
			*value = -125 * st->info.fss * 24909;
			*value2 = 100 * st->info.osdig * 100000;
			return IIO_VAL_FRACTIONAL;

		case IIO_TEMP:
			*value = -40 * 1000;
			return IIO_VAL_INT;

		default:
			return -EINVAL;
		}
	}

	return -EINVAL;
}

static const struct iio_info dlh_info = {
	.read_raw = dlh_read_raw,
};

static const struct iio_chan_spec dlh_channels[] = {
	{
		.type = IIO_PRESSURE,
		.indexed = 1,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
		.info_mask_shared_by_type =
			BIT(IIO_CHAN_INFO_SCALE) |
			BIT(IIO_CHAN_INFO_OFFSET),
		.scan_index = 0,
		.scan_type = {
			.sign = 'u',
			.realbits = DLH_NUM_PR_BITS,
			.storagebits = 32,
			.shift = 8,
			.endianness = IIO_BE,
		},
	}, {
		.type = IIO_TEMP,
		.indexed = 1,
		.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),
		.info_mask_shared_by_type =
			BIT(IIO_CHAN_INFO_SCALE) |
			BIT(IIO_CHAN_INFO_OFFSET),
		.scan_index = 1,
		.scan_type = {
			.sign = 'u',
			.realbits = DLH_NUM_TEMP_BITS,
			.storagebits = 32,
			.shift = 8,
			.endianness = IIO_BE,
		},
	}
};

static irqreturn_t dlh_trigger_handler(int irq, void *private)
{
	struct iio_poll_func *pf = private;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct dlh_state *st = iio_priv(indio_dev);
	int ret;
	unsigned int chn, i = 0;
	__be32 tmp_buf[2];

	ret = dlh_start_capture_and_read(st);
	if (ret)
		goto out;

	for_each_set_bit(chn, indio_dev->active_scan_mask,
		indio_dev->masklength) {
		memcpy(tmp_buf + i,
			&st->rx_buf[1] + chn * DLH_NUM_DATA_BYTES,
			DLH_NUM_DATA_BYTES);
		i++;
	}

	iio_push_to_buffers(indio_dev, tmp_buf);

out:
	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static irqreturn_t dlh_interrupt(int irq, void *private)
{
	struct iio_dev *indio_dev = private;
	struct dlh_state *st = iio_priv(indio_dev);

	complete(&st->completion);

	return IRQ_HANDLED;
};

static int dlh_probe(struct i2c_client *client,
	const struct i2c_device_id *id)
{
	struct dlh_state *st;
	struct iio_dev *indio_dev;
	int ret;

	if (!i2c_check_functionality(client->adapter,
		I2C_FUNC_I2C | I2C_FUNC_SMBUS_WRITE_BYTE)) {
		dev_err(&client->dev,
			"adapter doesn't support required i2c functionality\n");
		return -EOPNOTSUPP;
	}

	indio_dev = devm_iio_device_alloc(&client->dev, sizeof(*st));
	if (!indio_dev) {
		dev_err(&client->dev, "failed to allocate iio device\n");
		return -ENOMEM;
	}

	i2c_set_clientdata(client, indio_dev);

	st = iio_priv(indio_dev);
	st->info = dlh_info_tbl[id->driver_data];
	st->client = client;
	st->use_interrupt = false;

	indio_dev->name = id->name;
	indio_dev->dev.parent = &client->dev;
	indio_dev->dev.of_node = client->dev.of_node;
	indio_dev->info = &dlh_info;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->channels =  dlh_channels;
	indio_dev->num_channels = ARRAY_SIZE(dlh_channels);

	if (client->irq > 0) {
		ret = devm_request_threaded_irq(&client->dev, client->irq,
			dlh_interrupt, NULL,
			IRQF_TRIGGER_RISING | IRQF_ONESHOT,
			id->name, indio_dev);
		if (ret) {
			dev_err(&client->dev, "failed to allocate threaded irq");
			return ret;
		}

		st->use_interrupt = true;
		init_completion(&st->completion);
	}

	ret = devm_iio_triggered_buffer_setup(&client->dev, indio_dev,
		NULL, &dlh_trigger_handler, NULL);
	if (ret) {
		dev_err(&client->dev, "failed to setup iio buffer\n");
		return ret;
	}

	ret = devm_iio_device_register(&client->dev, indio_dev);
	if (ret)
		dev_err(&client->dev, "failed to register iio device\n");

	return ret;
}

static const struct of_device_id dlh_of_match[] = {
	{ .compatible = "asc,dlhl60d" },
	{ .compatible = "asc,dlhl60g" },
	{}
};
MODULE_DEVICE_TABLE(of, dlh_of_match);

static const struct i2c_device_id dlh_id[] = {
	{ "dlhl60d",    dlhl60d },
	{ "dlhl60g",    dlhl60g },
	{}
};
MODULE_DEVICE_TABLE(i2c, dlh_id);

static struct i2c_driver dlh_driver = {
	.driver = {
		.name = "dlhl60d",
		.of_match_table = dlh_of_match,
	},
	.probe = dlh_probe,
	.id_table = dlh_id,
};
module_i2c_driver(dlh_driver);

MODULE_AUTHOR("Tomislav Denis <tomislav.denis@avl.com>");
MODULE_DESCRIPTION("Driver for All Sensors DLH series pressure sensors");
MODULE_LICENSE("GPL v2");
