/*
 * Copyright (c) 2022 Intel Corporation
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/drivers/sensor.h>
#include <zephyr/drivers/adc/adc_npcx_threshold.h>
#include <zephyr/drivers/sensor/adc_cmp_npcx.h>
#include <zephyr/kernel.h>
#include <zephyr/logging/log.h>

LOG_MODULE_REGISTER(adc_cmp_npcx, CONFIG_SENSOR_LOG_LEVEL);

struct adc_cmp_npcx_data {
	/* Work queue to be notified when threshold assertion happens */
	struct k_work work;
	/* Sensor trigger hanlder to notify user of assetion */
	sensor_trigger_handler_t handler;
	/* ADC NPCX driver reference */
	const struct device *dev;
	/* Driver user sensor trigger reference */
	const struct sensor_trigger *trigger;
};

struct adc_cmp_npcx_config {
	/*
	 * Pointer of ADC device that will be performing measurement, this
	 * must be provied by device tree.
	 */
	const struct device *adc;
	/*
	 * ADC channel that will be used to measure signal, this must be
	 * provided by device tree.
	 */
	uint8_t chnsel;
	/* Threshold selection number assigned during initialization */
	uint8_t th_sel;
	/* Threshold assert value in millivolts */
	uint32_t thr_mv;
	/*
	 * Condition to be met between measured signal and threshold assert
	 * value that will trigger event
	 */
	enum adc_cmp_npcx_comparison comparison;
};

#define DT_DRV_COMPAT nuvoton_adc_cmp

#define ADC_CMP_NPCX_UNDEFINED		(-1)
static void adc_cmp_npcx_trigger_work_handler(struct k_work *item)
{
	struct adc_cmp_npcx_data *data =
			CONTAINER_OF(item, struct adc_cmp_npcx_data, work);

	if (data->handler) {
		data->handler(data->dev, data->trigger);
	}
}

static int adc_cmp_npcx_init(const struct device *dev)
{
	const struct adc_cmp_npcx_config *const config = dev->config;
	struct adc_cmp_npcx_data *data = dev->data;
	struct adc_npcx_threshold_param param;
	int ret;

	LOG_DBG("Initialize ADC CMP threshold selection (%d)", config->th_sel);
	/* Data must keep device reference for worker handler*/
	data->dev = dev;

	/* Set ADC channel selection */
	param.type = ADC_NPCX_THRESHOLD_PARAM_CHNSEL;
	param.val = (uint32_t)config->chnsel;
	ret = adc_npcx_threshold_ctrl_set_param(config->adc, config->th_sel,
						&param);
	if (ret) {
		goto init_error;
	}

	/* Init and set Worker queue to enable notifications */
	k_work_init(&data->work, adc_cmp_npcx_trigger_work_handler);
	param.type = ADC_NPCX_THRESHOLD_PARAM_WORK;
	param.val = (uint32_t)&data->work;
	ret = adc_npcx_threshold_ctrl_set_param(config->adc, config->th_sel,
						&param);
	if (ret) {
		goto init_error;
	}

	/* Set threshold value if set on device tree */
	if (config->thr_mv != ADC_CMP_NPCX_UNDEFINED) {
		param.type = ADC_NPCX_THRESHOLD_PARAM_THVAL;
		/* Convert from millivolts to ADC raw register value */
		ret = adc_npcx_threshold_mv_to_thrval(config->thr_mv,
						&param.val);
		if (ret) {
			goto init_error;
		}

		ret = adc_npcx_threshold_ctrl_set_param(config->adc,
				config->th_sel,	&param);
		if (ret) {
			goto init_error;
		}
	}

	/* Set threshold comparison if set on device tree */
	if (config->comparison == ADC_CMP_NPCX_GREATER ||
	    config->comparison == ADC_CMP_NPCX_LESS_OR_EQUAL) {
		param.type = ADC_NPCX_THRESHOLD_PARAM_L_H;
		param.val =
			config->comparison == ADC_CMP_NPCX_GREATER ?
			ADC_NPCX_THRESHOLD_PARAM_L_H_HIGHER :
			ADC_NPCX_THRESHOLD_PARAM_L_H_LOWER;
		ret = adc_npcx_threshold_ctrl_set_param(config->adc,
				config->th_sel,	&param);
	}

init_error:
	if (ret) {
		LOG_ERR("Error setting parameter %d - value %d",
			(uint32_t)param.type, param.val);
	}

	return ret;
}

static int adc_cmp_npcx_set_threshold(const struct device *dev, bool is_upper,
				      bool is_mv, uint32_t value)
{
	const struct adc_cmp_npcx_config *const config = dev->config;
	struct adc_npcx_threshold_param param;
	int ret;

	param.type = ADC_NPCX_THRESHOLD_PARAM_THVAL;
	if (is_mv) {
		ret = adc_npcx_threshold_mv_to_thrval(value, &param.val);
		if (ret) {
			return ret;
		}
	}

	ret = adc_npcx_threshold_ctrl_set_param(config->adc,
						config->th_sel, &param);
	if (ret) {
		return ret;
	}

	param.type = ADC_NPCX_THRESHOLD_PARAM_L_H;
	param.val = is_upper ? ADC_NPCX_THRESHOLD_PARAM_L_H_HIGHER :
		ADC_NPCX_THRESHOLD_PARAM_L_H_LOWER;

	ret = adc_npcx_threshold_ctrl_set_param(config->adc,
						config->th_sel, &param);

	return ret;
}

static int adc_cmp_npcx_attr_set(const struct device *dev,
			  enum sensor_channel chan,
			  enum sensor_attribute attr,
			  const struct sensor_value *val)
{
	const struct adc_cmp_npcx_config *const config = dev->config;
	int ret;

	if (chan != SENSOR_CHAN_VOLTAGE) {
		return -ENOTSUP;
	}

	switch ((uint16_t)attr) {
	case SENSOR_ATTR_LOWER_THRESH:
		__fallthrough;
	case SENSOR_ATTR_UPPER_THRESH:
		__fallthrough;
	case SENSOR_ATTR_LOWER_VOLTAGE_THRESH:
		__fallthrough;
	case SENSOR_ATTR_UPPER_VOLTAGE_THRESH:
		ret = adc_cmp_npcx_set_threshold(dev,
			/* Is upper? */
			attr == SENSOR_ATTR_UPPER_THRESH ||
			(uint16_t)attr == SENSOR_ATTR_UPPER_VOLTAGE_THRESH,
			/* Is mV? */
			(uint16_t)attr == SENSOR_ATTR_LOWER_VOLTAGE_THRESH ||
			(uint16_t)attr == SENSOR_ATTR_UPPER_VOLTAGE_THRESH,
			val->val1);
		break;
	case SENSOR_ATTR_ALERT:
		ret = adc_npcx_threshold_ctrl_enable(config->adc,
						config->th_sel, !!val->val1);
		break;
	default:
		ret = -ENOTSUP;
	}
	return ret;
}

static int adc_cmp_npcx_attr_get(const struct device *dev,
			  enum sensor_channel chan,
			  enum sensor_attribute attr,
			  struct sensor_value *val)
{
	return -ENOTSUP;
}

static int adc_cmp_npcx_trigger_set(const struct device *dev,
			     const struct sensor_trigger *trig,
			     sensor_trigger_handler_t handler)
{
	const struct adc_cmp_npcx_config *const config = dev->config;
	struct adc_cmp_npcx_data *data = dev->data;
	struct adc_npcx_threshold_param param;

	if (trig == NULL || handler == NULL) {
		return -EINVAL;
	}

	if (trig->type != SENSOR_TRIG_THRESHOLD ||
	    trig->chan != SENSOR_CHAN_VOLTAGE) {
		return -ENOTSUP;
	}

	data->handler = handler;
	data->trigger = trig;

	param.type = ADC_NPCX_THRESHOLD_PARAM_WORK;
	param.val = (uint32_t)&data->work;
	return adc_npcx_threshold_ctrl_set_param(config->adc, config->th_sel,
						&param);
}

static int adc_cmp_npcx_sample_fetch(const struct device *dev,
			      enum sensor_channel chan)
{
	return -ENOTSUP;
}

static int adc_cmp_npcx_channel_get(const struct device *dev,
			     enum sensor_channel chan,
			     struct sensor_value *val)
{
	return -ENOTSUP;
}

static const struct sensor_driver_api adc_cmp_npcx_api = {
	.attr_set = adc_cmp_npcx_attr_set,
	.attr_get = adc_cmp_npcx_attr_get,
	.trigger_set = adc_cmp_npcx_trigger_set,
	.sample_fetch = adc_cmp_npcx_sample_fetch,
	.channel_get = adc_cmp_npcx_channel_get,
};

#define NPCX_ADC_CMP_INIT(inst)                                               \
	static struct adc_cmp_npcx_data adc_cmp_npcx_data_##inst;             \
	static const struct adc_cmp_npcx_config adc_cmp_npcx_config_##inst = {\
		.adc = DEVICE_DT_GET(DT_INST_IO_CHANNELS_CTLR(inst)),         \
		.chnsel = DT_INST_IO_CHANNELS_INPUT(inst),                    \
		.th_sel = inst,                                               \
		.thr_mv = DT_INST_PROP_OR(inst, threshold_mv,                 \
			ADC_CMP_NPCX_UNDEFINED),                              \
		.comparison = DT_INST_STRING_TOKEN_OR(inst,                   \
			comparison, ADC_CMP_NPCX_UNDEFINED)                   \
	};                                                                    \
	SENSOR_DEVICE_DT_INST_DEFINE(inst, adc_cmp_npcx_init, NULL,           \
			      &adc_cmp_npcx_data_##inst,                      \
			      &adc_cmp_npcx_config_##inst, POST_KERNEL,       \
			      CONFIG_SENSOR_INIT_PRIORITY,                    \
			      &adc_cmp_npcx_api);
DT_INST_FOREACH_STATUS_OKAY(NPCX_ADC_CMP_INIT)
