// SPDX-License-Identifier: GPL-2.0-only
/*
 * BMA220 Digital triaxial acceleration sensor driver
 *
 * Copyright (c) 2016,2020 Intel Corporation.
 * Copyright (c) 2025 Petre Rodan  <petre.rodan@subdimension.ro>
 */

#include <linux/bits.h>
#include <linux/bitfield.h>
#include <linux/cleanup.h>
#include <linux/device.h>
#include <linux/errno.h>
#include <linux/module.h>
#include <linux/mutex.h>
#include <linux/pm.h>
#include <linux/regmap.h>
#include <linux/regulator/consumer.h>
#include <linux/types.h>

#include <linux/iio/buffer.h>
#include <linux/iio/iio.h>
#include <linux/iio/sysfs.h>
#include <linux/iio/trigger.h>
#include <linux/iio/trigger_consumer.h>
#include <linux/iio/triggered_buffer.h>

#include "bma220.h"

#define BMA220_REG_ID				0x00
#define BMA220_REG_REVISION_ID			0x01
#define BMA220_REG_ACCEL_X			0x02
#define BMA220_REG_ACCEL_Y			0x03
#define BMA220_REG_ACCEL_Z			0x04
#define BMA220_REG_CONF0			0x05
#define BMA220_HIGH_DUR_MSK			GENMASK(5, 0)
#define BMA220_HIGH_HY_MSK			GENMASK(7, 6)
#define BMA220_REG_CONF1			0x06
#define BMA220_HIGH_TH_MSK			GENMASK(3, 0)
#define BMA220_LOW_TH_MSK			GENMASK(7, 4)
#define BMA220_REG_CONF2			0x07
#define BMA220_LOW_DUR_MSK			GENMASK(5, 0)
#define BMA220_LOW_HY_MSK			GENMASK(7, 6)
#define BMA220_REG_CONF3			0x08
#define BMA220_TT_DUR_MSK			GENMASK(2, 0)
#define BMA220_TT_TH_MSK			GENMASK(6, 3)
#define BMA220_REG_CONF4			0x09
#define BMA220_SLOPE_DUR_MSK			GENMASK(1, 0)
#define BMA220_SLOPE_TH_MSK			GENMASK(5, 2)
#define BMA220_REG_CONF5			0x0a
#define BMA220_TIP_EN_MSK			BIT(4)
#define BMA220_REG_IF0				0x0b
#define BMA220_REG_IF1				0x0c
#define BMA220_IF_SLOPE				BIT(0)
#define BMA220_IF_DRDY				BIT(1)
#define BMA220_IF_HIGH				BIT(2)
#define BMA220_IF_LOW				BIT(3)
#define BMA220_IF_TT				BIT(4)
#define BMA220_REG_IE0				0x0d
#define BMA220_INT_EN_TAP_Z_MSK			BIT(0)
#define BMA220_INT_EN_TAP_Y_MSK			BIT(1)
#define BMA220_INT_EN_TAP_X_MSK			BIT(2)
#define BMA220_INT_EN_SLOPE_Z_MSK		BIT(3)
#define BMA220_INT_EN_SLOPE_Y_MSK		BIT(4)
#define BMA220_INT_EN_SLOPE_X_MSK		BIT(5)
#define BMA220_INT_EN_DRDY_MSK			BIT(7)
#define BMA220_REG_IE1				0x0e
#define BMA220_INT_EN_HIGH_Z_MSK		BIT(0)
#define BMA220_INT_EN_HIGH_Y_MSK		BIT(1)
#define BMA220_INT_EN_HIGH_X_MSK		BIT(2)
#define BMA220_INT_EN_LOW_MSK			BIT(3)
#define BMA220_INT_LATCH_MSK			GENMASK(6, 4)
#define BMA220_INT_RST_MSK			BIT(7)
#define BMA220_REG_IE2				0x0f
#define BMA220_REG_FILTER			0x10
#define BMA220_FILTER_MASK			GENMASK(3, 0)
#define BMA220_REG_RANGE			0x11
#define BMA220_RANGE_MASK			GENMASK(1, 0)
#define BMA220_REG_SUSPEND			0x18
#define BMA220_REG_SOFTRESET			0x19

#define BMA220_CHIP_ID				0xDD
#define BMA220_SUSPEND_SLEEP			0xFF
#define BMA220_SUSPEND_WAKE			0x00
#define BMA220_RESET_MODE			0xFF
#define BMA220_NONRESET_MODE			0x00

#define BMA220_DEVICE_NAME			"bma220"

#define BMA220_COF_1000Hz			0x0
#define BMA220_COF_500Hz			0x1
#define BMA220_COF_250Hz			0x2
#define BMA220_COF_125Hz			0x3
#define BMA220_COF_64Hz				0x4
#define BMA220_COF_32Hz				0x5

#define BMA220_ACCEL_CHANNEL(index, reg, axis) {			\
	.type = IIO_ACCEL,						\
	.address = reg,							\
	.modified = 1,							\
	.channel2 = IIO_MOD_##axis,					\
	.info_mask_separate = BIT(IIO_CHAN_INFO_RAW),			\
	.info_mask_shared_by_type = BIT(IIO_CHAN_INFO_SCALE) |		\
	    BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),		\
	.info_mask_shared_by_type_available = BIT(IIO_CHAN_INFO_SCALE) |\
	    BIT(IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY),		\
	.scan_index = index,						\
	.scan_type = {							\
		.sign = 's',						\
		.realbits = 6,						\
		.storagebits = 8,					\
		.shift = 2,						\
		.endianness = IIO_CPU,					\
	},								\
}

enum bma220_axis {
	AXIS_X,
	AXIS_Y,
	AXIS_Z,
};

static const int bma220_scale_table[][2] = {
	{ 0, 623000 }, { 1, 248000 }, { 2, 491000 }, { 4, 983000 },
};

struct bma220_data {
	struct regmap *regmap;
	struct mutex lock;
	u8 lpf_3dB_freq_idx;
	u8 range_idx;
	struct iio_trigger *trig;
	struct {
		s8 chans[3];
		/* Ensure timestamp is naturally aligned. */
		aligned_s64 timestamp;
	} scan __aligned(IIO_DMA_MINALIGN);
};

static const struct iio_chan_spec bma220_channels[] = {
	BMA220_ACCEL_CHANNEL(0, BMA220_REG_ACCEL_X, X),
	BMA220_ACCEL_CHANNEL(1, BMA220_REG_ACCEL_Y, Y),
	BMA220_ACCEL_CHANNEL(2, BMA220_REG_ACCEL_Z, Z),
	IIO_CHAN_SOFT_TIMESTAMP(3),
};

/* Available cut-off frequencies of the low pass filter in Hz. */
static const int bma220_lpf_3dB_freq_Hz_table[] = {
	[BMA220_COF_1000Hz] = 1000,
	[BMA220_COF_500Hz] = 500,
	[BMA220_COF_250Hz] = 250,
	[BMA220_COF_125Hz] = 125,
	[BMA220_COF_64Hz] = 64,
	[BMA220_COF_32Hz] = 32,
};

static const unsigned long bma220_accel_scan_masks[] = {
	BIT(AXIS_X) | BIT(AXIS_Y) | BIT(AXIS_Z),
	0
};

static bool bma220_is_writable_reg(struct device *dev, unsigned int reg)
{
	switch (reg) {
	case BMA220_REG_CONF0:
	case BMA220_REG_CONF1:
	case BMA220_REG_CONF2:
	case BMA220_REG_CONF3:
	case BMA220_REG_CONF4:
	case BMA220_REG_CONF5:
	case BMA220_REG_IE0:
	case BMA220_REG_IE1:
	case BMA220_REG_IE2:
	case BMA220_REG_FILTER:
	case BMA220_REG_RANGE:
	case BMA220_REG_WDT:
		return true;
	default:
		return false;
	}
}

const struct regmap_config bma220_spi_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.read_flag_mask = BIT(7),
	.max_register = BMA220_REG_SOFTRESET,
	.cache_type = REGCACHE_NONE,
	.writeable_reg = bma220_is_writable_reg,
};
EXPORT_SYMBOL_NS_GPL(bma220_spi_regmap_config, "IIO_BOSCH_BMA220");

/*
 * Based on the datasheet the memory map differs between the SPI and the I2C
 * implementations. I2C register addresses are simply shifted to the left
 * by 1 bit yet the register size remains unchanged.
 * This driver employs the SPI memory map to correlate register names to
 * addresses regardless of the bus type.
 */

const struct regmap_config bma220_i2c_regmap_config = {
	.reg_bits = 8,
	.val_bits = 8,
	.reg_shift = -1,
	.max_register = BMA220_REG_SOFTRESET,
	.cache_type = REGCACHE_NONE,
	.writeable_reg = bma220_is_writable_reg,
};
EXPORT_SYMBOL_NS_GPL(bma220_i2c_regmap_config, "IIO_BOSCH_BMA220");

static int bma220_data_rdy_trigger_set_state(struct iio_trigger *trig,
					     bool state)
{
	struct iio_dev *indio_dev = iio_trigger_get_drvdata(trig);
	struct bma220_data *data = iio_priv(indio_dev);

	return regmap_update_bits(data->regmap, BMA220_REG_IE0,
				  BMA220_INT_EN_DRDY_MSK,
				  FIELD_PREP(BMA220_INT_EN_DRDY_MSK, state));
}

static const struct iio_trigger_ops bma220_trigger_ops = {
	.set_trigger_state = &bma220_data_rdy_trigger_set_state,
	.validate_device = &iio_trigger_validate_own_device,
};

static irqreturn_t bma220_trigger_handler(int irq, void *p)
{
	int ret;
	struct iio_poll_func *pf = p;
	struct iio_dev *indio_dev = pf->indio_dev;
	struct bma220_data *data = iio_priv(indio_dev);

	ret = regmap_bulk_read(data->regmap, BMA220_REG_ACCEL_X,
			       &data->scan.chans,
			       sizeof(data->scan.chans));
	if (ret < 0)
		return IRQ_NONE;

	iio_push_to_buffers_with_ts(indio_dev, &data->scan, sizeof(data->scan),
				    iio_get_time_ns(indio_dev));
	iio_trigger_notify_done(indio_dev->trig);

	return IRQ_HANDLED;
}

static int bma220_read_raw(struct iio_dev *indio_dev,
			   struct iio_chan_spec const *chan,
			   int *val, int *val2, long mask)
{
	int ret;
	u8 index;
	unsigned int reg;
	struct bma220_data *data = iio_priv(indio_dev);

	guard(mutex)(&data->lock);

	switch (mask) {
	case IIO_CHAN_INFO_RAW:
		ret = regmap_read(data->regmap, chan->address, &reg);
		if (ret < 0)
			return -EINVAL;
		*val = sign_extend32(reg >> chan->scan_type.shift,
				     chan->scan_type.realbits - 1);
		return IIO_VAL_INT;
	case IIO_CHAN_INFO_SCALE:
		index = data->range_idx;
		*val = bma220_scale_table[index][0];
		*val2 = bma220_scale_table[index][1];
		return IIO_VAL_INT_PLUS_MICRO;
	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
		index = data->lpf_3dB_freq_idx;
		*val = bma220_lpf_3dB_freq_Hz_table[index];
		return IIO_VAL_INT;
	}

	return -EINVAL;
}

static int bma220_find_match_2dt(const int (*tbl)[2], const int n,
				 const int val, const int val2)
{
	int i;

	for (i = 0; i < n; i++) {
		if (tbl[i][0] == val && tbl[i][1] == val2)
			return i;
	}

	return -EINVAL;
}

static int bma220_find_match(const int *arr, const int n, const int val)
{
	int i;

	for (i = 0; i < n; i++) {
		if (arr[i] == val)
			return i;
	}

	return -EINVAL;
}

static int bma220_write_raw(struct iio_dev *indio_dev,
			    struct iio_chan_spec const *chan,
			    int val, int val2, long mask)
{
	int ret;
	int index = -1;
	struct bma220_data *data = iio_priv(indio_dev);

	guard(mutex)(&data->lock);

	switch (mask) {
	case IIO_CHAN_INFO_SCALE:
		index = bma220_find_match_2dt(bma220_scale_table,
					      ARRAY_SIZE(bma220_scale_table),
					      val, val2);
		if (index < 0)
			return -EINVAL;

		ret = regmap_update_bits(data->regmap, BMA220_REG_RANGE,
					 BMA220_RANGE_MASK,
					 FIELD_PREP(BMA220_RANGE_MASK, index));
		if (ret < 0)
			return ret;
		data->range_idx = index;

		return 0;
	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
		index = bma220_find_match(bma220_lpf_3dB_freq_Hz_table,
					  ARRAY_SIZE(bma220_lpf_3dB_freq_Hz_table),
					  val);
		if (index < 0)
			return -EINVAL;

		ret = regmap_update_bits(data->regmap, BMA220_REG_FILTER,
					 BMA220_FILTER_MASK,
					 FIELD_PREP(BMA220_FILTER_MASK, index));
		if (ret < 0)
			return ret;
		data->lpf_3dB_freq_idx = index;

		return 0;
	}

	return -EINVAL;
}

static int bma220_read_avail(struct iio_dev *indio_dev,
			     struct iio_chan_spec const *chan,
			     const int **vals, int *type, int *length,
			     long mask)
{
	switch (mask) {
	case IIO_CHAN_INFO_SCALE:
		*vals = (int *)bma220_scale_table;
		*type = IIO_VAL_INT_PLUS_MICRO;
		*length = ARRAY_SIZE(bma220_scale_table) * 2;
		return IIO_AVAIL_LIST;
	case IIO_CHAN_INFO_LOW_PASS_FILTER_3DB_FREQUENCY:
		*vals = (const int *)bma220_lpf_3dB_freq_Hz_table;
		*type = IIO_VAL_INT;
		*length = ARRAY_SIZE(bma220_lpf_3dB_freq_Hz_table);
		return IIO_AVAIL_LIST;
	default:
		return -EINVAL;
	}
}

static int bma220_reg_access(struct iio_dev *indio_dev, unsigned int reg,
			     unsigned int writeval, unsigned int *readval)
{
	struct bma220_data *data = iio_priv(indio_dev);

	if (readval)
		return regmap_read(data->regmap, reg, readval);
	return regmap_write(data->regmap, reg, writeval);
}

static const struct iio_info bma220_info = {
	.read_raw		= bma220_read_raw,
	.write_raw		= bma220_write_raw,
	.read_avail		= bma220_read_avail,
	.debugfs_reg_access	= &bma220_reg_access,
};

static int bma220_reset(struct bma220_data *data, bool up)
{
	int ret;
	unsigned int i, val;

	/*
	 * The chip can be reset by a simple register read.
	 * We need up to 2 register reads of the softreset register
	 * to make sure that the device is in the desired state.
	 */
	for (i = 0; i < 2; i++) {
		ret = regmap_read(data->regmap, BMA220_REG_SOFTRESET, &val);
		if (ret < 0)
			return ret;

		if (up && val == BMA220_RESET_MODE)
			return 0;

		if (!up && val == BMA220_NONRESET_MODE)
			return 0;
	}

	return -EBUSY;
}

static int bma220_power(struct bma220_data *data, bool up)
{
	int ret;
	unsigned int i, val;

	/*
	 * The chip can be suspended/woken up by a simple register read.
	 * So, we need up to 2 register reads of the suspend register
	 * to make sure that the device is in the desired state.
	 */
	for (i = 0; i < 2; i++) {
		ret = regmap_read(data->regmap, BMA220_REG_SUSPEND, &val);
		if (ret < 0)
			return ret;

		if (up && val == BMA220_SUSPEND_SLEEP)
			return 0;

		if (!up && val == BMA220_SUSPEND_WAKE)
			return 0;
	}

	return -EBUSY;
}

static int bma220_init(struct device *dev, struct bma220_data *data)
{
	int ret;
	unsigned int val;
	static const char * const regulator_names[] = { "vddd", "vddio", "vdda" };

	ret = devm_regulator_bulk_get_enable(dev,
					     ARRAY_SIZE(regulator_names),
					     regulator_names);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to get regulators\n");

	ret = regmap_read(data->regmap, BMA220_REG_ID, &val);
	if (ret)
		return dev_err_probe(dev, ret,
				     "Failed to read chip id register\n");

	if (val != BMA220_CHIP_ID)
		dev_info(dev, "Unknown chip found: 0x%02x\n", val);

	ret = bma220_power(data, true);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to power-on chip\n");

	ret = bma220_reset(data, true);
	if (ret)
		return dev_err_probe(dev, ret, "Failed to soft reset chip\n");

	return 0;
}

static void bma220_deinit(void *data_ptr)
{
	struct bma220_data *data = data_ptr;
	int ret;
	struct device *dev = regmap_get_device(data->regmap);

	ret = bma220_power(data, false);
	if (ret)
		dev_warn(dev,
			 "Failed to put device into suspend mode (%pe)\n",
			 ERR_PTR(ret));
}

static irqreturn_t bma220_irq_handler(int irq, void *private)
{
	struct iio_dev *indio_dev = private;
	struct bma220_data *data = iio_priv(indio_dev);
	int ret;
	unsigned int bma220_reg_if1;

	ret = regmap_read(data->regmap, BMA220_REG_IF1, &bma220_reg_if1);
	if (ret)
		return IRQ_NONE;

	if (FIELD_GET(BMA220_IF_DRDY, bma220_reg_if1))
		iio_trigger_poll_nested(data->trig);

	return IRQ_HANDLED;
}

int bma220_common_probe(struct device *dev, struct regmap *regmap, int irq)
{
	int ret;
	struct iio_dev *indio_dev;
	struct bma220_data *data;

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

	data = iio_priv(indio_dev);
	data->regmap = regmap;

	ret = bma220_init(dev, data);
	if (ret)
		return ret;

	ret = devm_mutex_init(dev, &data->lock);
	if (ret)
		return ret;

	indio_dev->info = &bma220_info;
	indio_dev->name = BMA220_DEVICE_NAME;
	indio_dev->modes = INDIO_DIRECT_MODE;
	indio_dev->channels = bma220_channels;
	indio_dev->num_channels = ARRAY_SIZE(bma220_channels);
	indio_dev->available_scan_masks = bma220_accel_scan_masks;

	if (irq > 0) {
		data->trig = devm_iio_trigger_alloc(dev, "%s-dev%d",
						    indio_dev->name,
						    iio_device_id(indio_dev));
		if (!data->trig)
			return -ENOMEM;

		data->trig->ops = &bma220_trigger_ops;
		iio_trigger_set_drvdata(data->trig, indio_dev);

		ret = devm_iio_trigger_register(dev, data->trig);
		if (ret)
			return dev_err_probe(dev, ret,
					     "iio trigger register fail\n");
		indio_dev->trig = iio_trigger_get(data->trig);
		ret = devm_request_threaded_irq(dev, irq, NULL,
						&bma220_irq_handler, IRQF_ONESHOT,
						indio_dev->name, indio_dev);
		if (ret)
			return ret;
	}

	ret = devm_add_action_or_reset(dev, bma220_deinit, data);
	if (ret)
		return ret;

	ret = devm_iio_triggered_buffer_setup(dev, indio_dev, NULL,
					      bma220_trigger_handler, NULL);
	if (ret < 0)
		dev_err_probe(dev, ret, "iio triggered buffer setup failed\n");

	return devm_iio_device_register(dev, indio_dev);
}
EXPORT_SYMBOL_NS_GPL(bma220_common_probe, "IIO_BOSCH_BMA220");

static int bma220_suspend(struct device *dev)
{
	struct iio_dev *indio_dev = dev_get_drvdata(dev);
	struct bma220_data *data = iio_priv(indio_dev);

	return bma220_power(data, false);
}

static int bma220_resume(struct device *dev)
{
	struct iio_dev *indio_dev = dev_get_drvdata(dev);
	struct bma220_data *data = iio_priv(indio_dev);

	return bma220_power(data, true);
}
EXPORT_NS_SIMPLE_DEV_PM_OPS(bma220_pm_ops, bma220_suspend, bma220_resume,
			    IIO_BOSCH_BMA220);

MODULE_AUTHOR("Tiberiu Breana <tiberiu.a.breana@intel.com>");
MODULE_DESCRIPTION("BMA220 acceleration sensor driver");
MODULE_LICENSE("GPL");
