// SPDX-License-Identifier: GPL-2.0-only
/*
 * Xilinx XADC driver
 *
 * Copyright 2013 Analog Devices Inc.
 *  Author: Lars-Peter Clauen <lars@metafoo.de>
 */

#include <linux/iio/events.h>
#include <linux/iio/iio.h>
#include <linux/kernel.h>

#include "xilinx-xadc.h"

static const struct iio_chan_spec *xadc_event_to_channel(
	struct iio_dev *indio_dev, unsigned int event)
{
	switch (event) {
	case XADC_THRESHOLD_OT_MAX:
	case XADC_THRESHOLD_TEMP_MAX:
		return &indio_dev->channels[0];
	case XADC_THRESHOLD_VCCINT_MAX:
	case XADC_THRESHOLD_VCCAUX_MAX:
		return &indio_dev->channels[event];
	default:
		return &indio_dev->channels[event-1];
	}
}

static void xadc_handle_event(struct iio_dev *indio_dev, unsigned int event)
{
	const struct iio_chan_spec *chan;

	/* Temperature threshold error, we don't handle this yet */
	if (event == 0)
		return;

	chan = xadc_event_to_channel(indio_dev, event);

	if (chan->type == IIO_TEMP) {
		/*
		 * The temperature channel only supports over-temperature
		 * events.
		 */
		iio_push_event(indio_dev,
			IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
				IIO_EV_TYPE_THRESH, IIO_EV_DIR_RISING),
			iio_get_time_ns(indio_dev));
	} else {
		/*
		 * For other channels we don't know whether it is a upper or
		 * lower threshold event. Userspace will have to check the
		 * channel value if it wants to know.
		 */
		iio_push_event(indio_dev,
			IIO_UNMOD_EVENT_CODE(chan->type, chan->channel,
				IIO_EV_TYPE_THRESH, IIO_EV_DIR_EITHER),
			iio_get_time_ns(indio_dev));
	}
}

void xadc_handle_events(struct iio_dev *indio_dev, unsigned long events)
{
	unsigned int i;

	for_each_set_bit(i, &events, 8)
		xadc_handle_event(indio_dev, i);
}

static unsigned int xadc_get_threshold_offset(const struct iio_chan_spec *chan,
	enum iio_event_direction dir)
{
	unsigned int offset;

	if (chan->type == IIO_TEMP) {
		offset = XADC_THRESHOLD_OT_MAX;
	} else {
		if (chan->channel < 2)
			offset = chan->channel + 1;
		else
			offset = chan->channel + 6;
	}

	if (dir == IIO_EV_DIR_FALLING)
		offset += 4;

	return offset;
}

static unsigned int xadc_get_alarm_mask(const struct iio_chan_spec *chan)
{
	if (chan->type == IIO_TEMP)
		return XADC_ALARM_OT_MASK;
	switch (chan->channel) {
	case 0:
		return XADC_ALARM_VCCINT_MASK;
	case 1:
		return XADC_ALARM_VCCAUX_MASK;
	case 2:
		return XADC_ALARM_VCCBRAM_MASK;
	case 3:
		return XADC_ALARM_VCCPINT_MASK;
	case 4:
		return XADC_ALARM_VCCPAUX_MASK;
	case 5:
		return XADC_ALARM_VCCODDR_MASK;
	default:
		/* We will never get here */
		return 0;
	}
}

int xadc_read_event_config(struct iio_dev *indio_dev,
	const struct iio_chan_spec *chan, enum iio_event_type type,
	enum iio_event_direction dir)
{
	struct xadc *xadc = iio_priv(indio_dev);

	return (bool)(xadc->alarm_mask & xadc_get_alarm_mask(chan));
}

int xadc_write_event_config(struct iio_dev *indio_dev,
	const struct iio_chan_spec *chan, enum iio_event_type type,
	enum iio_event_direction dir, int state)
{
	unsigned int alarm = xadc_get_alarm_mask(chan);
	struct xadc *xadc = iio_priv(indio_dev);
	uint16_t cfg, old_cfg;
	int ret;

	mutex_lock(&xadc->mutex);

	if (state)
		xadc->alarm_mask |= alarm;
	else
		xadc->alarm_mask &= ~alarm;

	xadc->ops->update_alarm(xadc, xadc->alarm_mask);

	ret = _xadc_read_adc_reg(xadc, XADC_REG_CONF1, &cfg);
	if (ret)
		goto err_out;

	old_cfg = cfg;
	cfg |= XADC_CONF1_ALARM_MASK;
	cfg &= ~((xadc->alarm_mask & 0xf0) << 4); /* bram, pint, paux, ddr */
	cfg &= ~((xadc->alarm_mask & 0x08) >> 3); /* ot */
	cfg &= ~((xadc->alarm_mask & 0x07) << 1); /* temp, vccint, vccaux */
	if (old_cfg != cfg)
		ret = _xadc_write_adc_reg(xadc, XADC_REG_CONF1, cfg);

err_out:
	mutex_unlock(&xadc->mutex);

	return ret;
}

/* Register value is msb aligned, the lower 4 bits are ignored */
#define XADC_THRESHOLD_VALUE_SHIFT 4

int xadc_read_event_value(struct iio_dev *indio_dev,
	const struct iio_chan_spec *chan, enum iio_event_type type,
	enum iio_event_direction dir, enum iio_event_info info,
	int *val, int *val2)
{
	unsigned int offset = xadc_get_threshold_offset(chan, dir);
	struct xadc *xadc = iio_priv(indio_dev);

	switch (info) {
	case IIO_EV_INFO_VALUE:
		*val = xadc->threshold[offset];
		break;
	case IIO_EV_INFO_HYSTERESIS:
		*val = xadc->temp_hysteresis;
		break;
	default:
		return -EINVAL;
	}

	*val >>= XADC_THRESHOLD_VALUE_SHIFT;

	return IIO_VAL_INT;
}

int xadc_write_event_value(struct iio_dev *indio_dev,
	const struct iio_chan_spec *chan, enum iio_event_type type,
	enum iio_event_direction dir, enum iio_event_info info,
	int val, int val2)
{
	unsigned int offset = xadc_get_threshold_offset(chan, dir);
	struct xadc *xadc = iio_priv(indio_dev);
	int ret = 0;

	val <<= XADC_THRESHOLD_VALUE_SHIFT;

	if (val < 0 || val > 0xffff)
		return -EINVAL;

	mutex_lock(&xadc->mutex);

	switch (info) {
	case IIO_EV_INFO_VALUE:
		xadc->threshold[offset] = val;
		break;
	case IIO_EV_INFO_HYSTERESIS:
		xadc->temp_hysteresis = val;
		break;
	default:
		mutex_unlock(&xadc->mutex);
		return -EINVAL;
	}

	if (chan->type == IIO_TEMP) {
		/*
		 * According to the datasheet we need to set the lower 4 bits to
		 * 0x3, otherwise 125 degree celsius will be used as the
		 * threshold.
		 */
		val |= 0x3;

		/*
		 * Since we store the hysteresis as relative (to the threshold)
		 * value, but the hardware expects an absolute value we need to
		 * recalcualte this value whenever the hysteresis or the
		 * threshold changes.
		 */
		if (xadc->threshold[offset] < xadc->temp_hysteresis)
			xadc->threshold[offset + 4] = 0;
		else
			xadc->threshold[offset + 4] = xadc->threshold[offset] -
					xadc->temp_hysteresis;
		ret = _xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(offset + 4),
			xadc->threshold[offset + 4]);
		if (ret)
			goto out_unlock;
	}

	if (info == IIO_EV_INFO_VALUE)
		ret = _xadc_write_adc_reg(xadc, XADC_REG_THRESHOLD(offset), val);

out_unlock:
	mutex_unlock(&xadc->mutex);

	return ret;
}
