/*
 * Copyright (c) 2023 Grinn
 * SPDX-License-Identifier: Apache-2.0
 */

#define DT_DRV_COMPAT adi_ad559x_adc

#include <zephyr/drivers/adc.h>
#include <zephyr/kernel.h>
#include <zephyr/sys/byteorder.h>

#include <zephyr/drivers/mfd/ad559x.h>

#define ADC_CONTEXT_USES_KERNEL_TIMER
#include "adc_context.h"

#include <zephyr/logging/log.h>
LOG_MODULE_REGISTER(adc_ad559x, CONFIG_ADC_LOG_LEVEL);

#define AD559X_ADC_RD_POINTER_SIZE 1
#define AD559X_ADC_RD_POINTER      0x40

#define AD559X_ADC_RESOLUTION 12U
#define AD559X_ADC_VREF_MV 2500U

#define AD559X_ADC_RES_IND_BIT BIT(15)
#define AD559X_ADC_RES_CHAN_MASK GENMASK(14, 12)
#define AD559X_ADC_RES_VAL_MASK GENMASK(11, 0)

struct adc_ad559x_config {
	const struct device *mfd_dev;
};

struct adc_ad559x_data {
	struct adc_context ctx;
	const struct device *dev;
	uint8_t adc_conf;
	uint16_t *buffer;
	uint16_t *repeat_buffer;
	uint8_t channels;
	struct k_thread thread;
	struct k_sem sem;

	K_KERNEL_STACK_MEMBER(stack, CONFIG_ADC_AD559X_ACQUISITION_THREAD_STACK_SIZE);
};

static int adc_ad559x_channel_setup(const struct device *dev,
				    const struct adc_channel_cfg *channel_cfg)
{
	const struct adc_ad559x_config *config = dev->config;
	struct adc_ad559x_data *data = dev->data;

	if (channel_cfg->channel_id >= AD559X_PIN_MAX) {
		LOG_ERR("invalid channel id %d", channel_cfg->channel_id);
		return -EINVAL;
	}

	data->adc_conf |= BIT(channel_cfg->channel_id);

	return mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_ADC_CONFIG, data->adc_conf);
}

static int adc_ad559x_validate_buffer_size(const struct device *dev,
					   const struct adc_sequence *sequence)
{
	uint8_t channels;
	size_t needed;

	channels = POPCOUNT(sequence->channels);
	needed = channels * sizeof(uint16_t);

	if (sequence->buffer_size < needed) {
		return -ENOMEM;
	}

	return 0;
}

static int adc_ad559x_start_read(const struct device *dev, const struct adc_sequence *sequence)
{
	struct adc_ad559x_data *data = dev->data;
	int ret;

	if (sequence->resolution != AD559X_ADC_RESOLUTION) {
		LOG_ERR("invalid resolution %d", sequence->resolution);
		return -EINVAL;
	}

	if (find_msb_set(sequence->channels) > AD559X_PIN_MAX) {
		LOG_ERR("invalid channels in mask: 0x%08x", sequence->channels);
		return -EINVAL;
	}

	ret = adc_ad559x_validate_buffer_size(dev, sequence);
	if (ret < 0) {
		LOG_ERR("insufficient buffer size");
		return ret;
	}

	data->buffer = sequence->buffer;
	adc_context_start_read(&data->ctx, sequence);

	return adc_context_wait_for_completion(&data->ctx);
}

static int adc_ad559x_read_channel(const struct device *dev, uint8_t channel, uint16_t *result)
{
	const struct adc_ad559x_config *config = dev->config;
	uint16_t val;
	uint8_t conv_channel;
	int ret;

	/* Select channel */
	ret = mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_SEQ_ADC, BIT(channel));
	if (ret < 0) {
		return ret;
	}

	if (mfd_ad559x_has_pointer_byte_map(config->mfd_dev)) {
		/* Start readback */
		val = AD559X_ADC_RD_POINTER;
		ret = mfd_ad559x_write_raw(config->mfd_dev, (uint8_t *)&val,
					   AD559X_ADC_RD_POINTER_SIZE);
		if (ret < 0) {
			return ret;
		}

		/* Read channel */
		ret = mfd_ad559x_read_raw(config->mfd_dev, (uint8_t *)&val, sizeof(val));
		if (ret < 0) {
			return ret;
		}

		*result = sys_get_be16((uint8_t *)&val);

	} else {
		/*
		 * Invalid data:
		 * See Figure 46. Single-Channel ADC Conversion Sequence.
		 * The first conversion result always returns invalid data.
		 */
		(void)mfd_ad559x_read_raw(config->mfd_dev, (uint8_t *)&val, sizeof(val));

		ret = mfd_ad559x_read_raw(config->mfd_dev, (uint8_t *)&val, sizeof(val));
		if (ret < 0) {
			return ret;
		}

		val = sys_be16_to_cpu(val);

		/*
		 * Invalid data:
		 * See "ADC section" in "Theory of operation" chapter.
		 * Valid ADC result has MSB bit set to 0.
		 */
		if ((val & AD559X_ADC_RES_IND_BIT) != 0) {
			return -EAGAIN;
		}

		/*
		 * Invalid channel converted:
		 * See "ADC section" in "Theory of operation" chapter.
		 * Conversion result contains channel number which should match requested channel.
		 */
		conv_channel = FIELD_GET(AD559X_ADC_RES_CHAN_MASK, val);
		if (conv_channel != channel) {
			return -EIO;
		}

		*result = val & AD559X_ADC_RES_VAL_MASK;
	}

	return 0;
}

static void adc_context_start_sampling(struct adc_context *ctx)
{
	struct adc_ad559x_data *data = CONTAINER_OF(ctx, struct adc_ad559x_data, ctx);

	data->channels = ctx->sequence.channels;
	data->repeat_buffer = data->buffer;

	k_sem_give(&data->sem);
}

static void adc_context_update_buffer_pointer(struct adc_context *ctx, bool repeat_sampling)
{
	struct adc_ad559x_data *data = CONTAINER_OF(ctx, struct adc_ad559x_data, ctx);

	if (repeat_sampling) {
		data->buffer = data->repeat_buffer;
	}
}

static void adc_ad559x_acquisition_thread(struct adc_ad559x_data *data)
{
	uint16_t result;
	uint8_t channel;
	int ret;

	while (true) {
		k_sem_take(&data->sem, K_FOREVER);

		while (data->channels != 0) {
			channel = find_lsb_set(data->channels) - 1;

			ret = adc_ad559x_read_channel(data->dev, channel, &result);
			if (ret < 0) {
				LOG_ERR("failed to read channel %d (ret %d)", channel, ret);
				adc_context_complete(&data->ctx, ret);
				break;
			}

			*data->buffer++ = result;
			WRITE_BIT(data->channels, channel, 0);
		}

		adc_context_on_sampling_done(&data->ctx, data->dev);
	}
}

static int adc_ad559x_read_async(const struct device *dev, const struct adc_sequence *sequence,
				 struct k_poll_signal *async)
{
	struct adc_ad559x_data *data = dev->data;
	int ret;

	adc_context_lock(&data->ctx, async ? true : false, async);
	ret = adc_ad559x_start_read(dev, sequence);
	adc_context_release(&data->ctx, ret);

	return ret;
}

static int adc_ad559x_read(const struct device *dev, const struct adc_sequence *sequence)
{
	return adc_ad559x_read_async(dev, sequence, NULL);
}

static int adc_ad559x_init(const struct device *dev)
{
	const struct adc_ad559x_config *config = dev->config;
	struct adc_ad559x_data *data = dev->data;
	k_tid_t tid;
	int ret;

	if (!device_is_ready(config->mfd_dev)) {
		return -ENODEV;
	}

	ret = mfd_ad559x_write_reg(config->mfd_dev, AD559X_REG_PD_REF_CTRL, AD559X_EN_REF);
	if (ret < 0) {
		return ret;
	}

	data->dev = dev;

	k_sem_init(&data->sem, 0, 1);
	adc_context_init(&data->ctx);

	tid = k_thread_create(&data->thread, data->stack,
			K_KERNEL_STACK_SIZEOF(data->stack),
			(k_thread_entry_t)adc_ad559x_acquisition_thread, data, NULL, NULL,
			CONFIG_ADC_AD559X_ACQUISITION_THREAD_PRIO, 0, K_NO_WAIT);

	if (IS_ENABLED(CONFIG_THREAD_NAME)) {
		ret = k_thread_name_set(tid, "adc_ad559x");
		if (ret < 0) {
			return ret;
		}
	}

	adc_context_unlock_unconditionally(&data->ctx);

	return 0;
}

static const struct adc_driver_api adc_ad559x_api = {
	.channel_setup = adc_ad559x_channel_setup,
	.read = adc_ad559x_read,
#ifdef CONFIG_ADC_ASYNC
	.read_async = adc_ad559x_read_async,
#endif
	.ref_internal = AD559X_ADC_VREF_MV,
};

#define ADC_AD559X_DEFINE(inst)                                                                    \
	static const struct adc_ad559x_config adc_ad559x_config##inst = {                          \
		.mfd_dev = DEVICE_DT_GET(DT_INST_PARENT(inst)),                                    \
	};                                                                                         \
                                                                                                   \
	static struct adc_ad559x_data adc_ad559x_data##inst;                                       \
                                                                                                   \
	DEVICE_DT_INST_DEFINE(inst, adc_ad559x_init, NULL, &adc_ad559x_data##inst,                 \
			      &adc_ad559x_config##inst, POST_KERNEL, CONFIG_MFD_INIT_PRIORITY,     \
			      &adc_ad559x_api);

DT_INST_FOREACH_STATUS_OKAY(ADC_AD559X_DEFINE)
