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

#include <errno.h>

#include <stdio.h>
#include <kernel.h>
#include <soc.h>
#include <device.h>
#include <init.h>
#include <aio_comparator.h>

#include "qm_comparator.h"

#define INT_COMPARATORS_MASK 0x7FFFF
#define AIO_QMSI_CMP_COUNT		(19)
#if (QM_LAKEMONT)
#define CMP_INTR_ROUTER QM_INTERRUPT_ROUTER->comparator_0_host_int_mask
#else
#define CMP_INTR_ROUTER QM_INTERRUPT_ROUTER->comparator_0_ss_int_mask
#endif

struct aio_qmsi_cmp_cb {
	aio_cmp_cb cb;
	void *param;
};

struct aio_qmsi_cmp_dev_data_t {
	/** Number of total comparators */
	u8_t num_cmp;
	/** Callback for each comparator */
	struct aio_qmsi_cmp_cb cb[AIO_QMSI_CMP_COUNT];
};

/* Shadow configuration to keep track of changes */
static qm_ac_config_t config;

static int aio_cmp_config(struct device *dev);

static int aio_qmsi_cmp_disable(struct device *dev, u8_t index)
{
	if (index >= AIO_QMSI_CMP_COUNT) {
		return -EINVAL;
	}

	/* Disable interrupt to current core */
	CMP_INTR_ROUTER |= (1 << index);

	/* Disable comparator according to index */
	config.cmp_en &= ~(1 << index);
	config.power &= ~(1 << index);
	config.reference &= ~(1 << index);
	config.polarity &= ~(1 << index);

	if (qm_ac_set_config(&config) != 0) {
		return -EINVAL;
	}

	return 0;
}

static int aio_qmsi_cmp_configure(struct device *dev, u8_t index,
			 enum aio_cmp_polarity polarity,
			 enum aio_cmp_ref refsel,
			 aio_cmp_cb cb, void *param)
{
	struct aio_qmsi_cmp_dev_data_t *dev_data =
		(struct aio_qmsi_cmp_dev_data_t *)dev->driver_data;

	if (index >= AIO_QMSI_CMP_COUNT) {
		return -EINVAL;
	}

	aio_qmsi_cmp_disable(dev, index);

	dev_data->cb[index].cb = cb;
	dev_data->cb[index].param = param;

	if (refsel == AIO_CMP_REF_A) {
		config.reference &= ~(1 << index);
	} else {
		config.reference |= (1 << index);
	}

	if (polarity == AIO_CMP_POL_RISE) {
		config.polarity &= ~(1 << index);
	} else {
		config.polarity |= (1 << index);
	}
	/* The driver will not use QMSI callback mechanism */
	config.callback = NULL;
	/* Enable comparator */
	config.cmp_en |= (1 << index);
	config.power |= (1 << index);

	if (qm_ac_set_config(&config) != 0) {
		return -EINVAL;
	}

	/* Enable Interrupts to current core for an specific comparator */
	CMP_INTR_ROUTER &= ~(1 << index);

	return 0;
}

static u32_t aio_cmp_qmsi_get_pending_int(struct device *dev)
{
	return QM_SCSS_CMP->cmp_stat_clr;
}

static const struct aio_cmp_driver_api aio_cmp_funcs = {
	.disable = aio_qmsi_cmp_disable,
	.configure = aio_qmsi_cmp_configure,
	.get_pending_int = aio_cmp_qmsi_get_pending_int,
};

static int aio_qmsi_cmp_init(struct device *dev)
{
	u8_t i;
	struct aio_qmsi_cmp_dev_data_t *dev_data =
		(struct aio_qmsi_cmp_dev_data_t *)dev->driver_data;

	aio_cmp_config(dev);

	/* Disable all comparator interrupts */
	CMP_INTR_ROUTER |= INT_COMPARATORS_MASK;

	/* Clear status and dissble all comparators */
	QM_SCSS_CMP->cmp_stat_clr |= INT_COMPARATORS_MASK;
	QM_SCSS_CMP->cmp_pwr &= ~INT_COMPARATORS_MASK;
	QM_SCSS_CMP->cmp_en &= ~INT_COMPARATORS_MASK;

	/* Don't use the QMSI callback */
	config.callback = NULL;
	/* Get Initial configuration from HW */
	config.reference = QM_SCSS_CMP->cmp_ref_sel;
	config.polarity = QM_SCSS_CMP->cmp_ref_pol;
	config.power = QM_SCSS_CMP->cmp_pwr;
	config.cmp_en = QM_SCSS_CMP->cmp_en;

	/* Clear callback pointers */
	for (i = 0U; i < dev_data->num_cmp; i++) {
		dev_data->cb[i].cb = NULL;
		dev_data->cb[i].param = NULL;
	}

	irq_enable(IRQ_GET_NUMBER(QM_IRQ_COMPARATOR_0_INT));

	return 0;
}

static void aio_qmsi_cmp_isr(void *data)
{
	u8_t i;
	struct device *dev = data;
	struct aio_qmsi_cmp_dev_data_t *dev_data =
		(struct aio_qmsi_cmp_dev_data_t *)dev->driver_data;

	u32_t int_status = QM_SCSS_CMP->cmp_stat_clr;

	for (i = 0U; i < dev_data->num_cmp; i++) {
		if (int_status & (1 << i)) {
			if (dev_data->cb[i].cb != NULL) {
				dev_data->cb[i].cb(dev_data->cb[i].param);
			}
		}
	}

	/* Clear all pending interrupts */
	QM_SCSS_CMP->cmp_stat_clr = int_status;
}

static struct aio_qmsi_cmp_dev_data_t aio_qmsi_cmp_dev_data = {
		.num_cmp = AIO_QMSI_CMP_COUNT,
};

DEVICE_AND_API_INIT(aio_qmsi_cmp, CONFIG_AIO_COMPARATOR_0_NAME,
		    &aio_qmsi_cmp_init, &aio_qmsi_cmp_dev_data, NULL,
		    POST_KERNEL, CONFIG_KERNEL_INIT_PRIORITY_DEVICE,
		    (void *)&aio_cmp_funcs);

static int aio_cmp_config(struct device *dev)
{
	ARG_UNUSED(dev);

	IRQ_CONNECT(IRQ_GET_NUMBER(QM_IRQ_COMPARATOR_0_INT),
		    CONFIG_AIO_COMPARATOR_0_IRQ_PRI, aio_qmsi_cmp_isr,
		    DEVICE_GET(aio_qmsi_cmp), 0);

	return 0;
}
