/*
 * Copyright (c) 2023 ITE Corporation. All Rights Reserved
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <zephyr/kernel.h>
#include <zephyr/arch/cpu.h>
#include <zephyr/init.h>
#include <zephyr/logging/log.h>
#include <zephyr/sys/printk.h>
#include <zephyr/sw_isr_table.h>
#include "intc_ite_it8xxx2.h"
LOG_MODULE_REGISTER(intc_it8xxx2_v2, LOG_LEVEL_DBG);

#define IT8XXX2_INTC_BASE		DT_REG_ADDR(DT_NODELABEL(intc))
#define IT8XXX2_INTC_BASE_SHIFT(g)	(IT8XXX2_INTC_BASE + ((g) << 2))

/* Interrupt status register */
#define IT8XXX2_INTC_ISR(g)	ECREG(IT8XXX2_INTC_BASE_SHIFT(g) + \
				((g) < 4 ? 0x0 : 0x4))
/* Interrupt enable register */
#define IT8XXX2_INTC_IER(g)	ECREG(IT8XXX2_INTC_BASE_SHIFT(g) + \
				((g) < 4 ? 0x1 : 0x5))
/* Interrupt edge/level triggered mode register */
#define IT8XXX2_INTC_IELMR(g)	ECREG(IT8XXX2_INTC_BASE_SHIFT(g) + \
				((g) < 4 ? 0x2 : 0x6))
/* Interrupt polarity register */
#define IT8XXX2_INTC_IPOLR(g)	ECREG(IT8XXX2_INTC_BASE_SHIFT(g) + \
				((g) < 4 ? 0x3 : 0x7))

#define IT8XXX2_INTC_GROUP_CNT      24
#define MAX_REGISR_IRQ_NUM          8
#define IVECT_OFFSET_WITH_IRQ       0x10

/* Interrupt number of INTC module */
static uint8_t intc_irq;
static uint8_t ier_setting[IT8XXX2_INTC_GROUP_CNT];

void ite_intc_save_and_disable_interrupts(void)
{
	/* Disable global interrupt for critical section */
	unsigned int key = irq_lock();

	/* Save and disable interrupts */
	for (int i = 0; i < IT8XXX2_INTC_GROUP_CNT; i++) {
		ier_setting[i] = IT8XXX2_INTC_IER(i);
		IT8XXX2_INTC_IER(i) = 0;
	}

	/*
	 * This load operation will guarantee the above modification of
	 * SOC's register can be seen by any following instructions.
	 * Note: Barrier instruction can not synchronize chip register,
	 * so we introduce workaround here.
	 */
	IT8XXX2_INTC_IER(IT8XXX2_INTC_GROUP_CNT - 1);

	irq_unlock(key);
}

void ite_intc_restore_interrupts(void)
{
	/*
	 * Ensure the highest priority interrupt will be the first fired
	 * interrupt when soc is ready to go.
	 */
	unsigned int key = irq_lock();

	/* Restore interrupt state */
	for (int i = 0; i < IT8XXX2_INTC_GROUP_CNT; i++) {
		IT8XXX2_INTC_IER(i) = ier_setting[i];
	}

	irq_unlock(key);
}

void ite_intc_isr_clear(unsigned int irq)
{
	uint32_t group, index;

	if (irq > CONFIG_NUM_IRQS) {
		return;
	}

	group = irq / MAX_REGISR_IRQ_NUM;
	index = irq % MAX_REGISR_IRQ_NUM;

	IT8XXX2_INTC_ISR(group) = BIT(index);
}

void __soc_ram_code ite_intc_irq_enable(unsigned int irq)
{
	uint32_t group, index;

	if (irq > CONFIG_NUM_IRQS) {
		return;
	}

	group = irq / MAX_REGISR_IRQ_NUM;
	index = irq % MAX_REGISR_IRQ_NUM;

	/* Critical section due to run a bit-wise OR operation */
	unsigned int key = irq_lock();

	IT8XXX2_INTC_IER(group) |= BIT(index);

	irq_unlock(key);
}

void __soc_ram_code ite_intc_irq_disable(unsigned int irq)
{
	uint32_t group, index;

	if (irq > CONFIG_NUM_IRQS) {
		return;
	}

	group = irq / MAX_REGISR_IRQ_NUM;
	index = irq % MAX_REGISR_IRQ_NUM;

	/* Critical section due to run a bit-wise NAND operation */
	unsigned int key = irq_lock();

	IT8XXX2_INTC_IER(group) &= ~BIT(index);
	/*
	 * This load operation will guarantee the above modification of
	 * SOC's register can be seen by any following instructions.
	 */
	IT8XXX2_INTC_IER(group);

	irq_unlock(key);
}

void ite_intc_irq_polarity_set(unsigned int irq, unsigned int flags)
{
	uint32_t group, index;

	if (irq > CONFIG_NUM_IRQS) {
		return;
	}

	if ((flags & IRQ_TYPE_EDGE_BOTH) == IRQ_TYPE_EDGE_BOTH) {
		return;
	}

	group = irq / MAX_REGISR_IRQ_NUM;
	index = irq % MAX_REGISR_IRQ_NUM;

	if ((flags & IRQ_TYPE_LEVEL_HIGH) || (flags & IRQ_TYPE_EDGE_RISING)) {
		IT8XXX2_INTC_IPOLR(group) &= ~BIT(index);
	} else {
		IT8XXX2_INTC_IPOLR(group) |= BIT(index);
	}

	if ((flags & IRQ_TYPE_LEVEL_LOW) || (flags & IRQ_TYPE_LEVEL_HIGH)) {
		IT8XXX2_INTC_IELMR(group) &= ~BIT(index);
	} else {
		IT8XXX2_INTC_IELMR(group) |= BIT(index);
	}
}

int __soc_ram_code ite_intc_irq_is_enable(unsigned int irq)
{
	uint32_t group, index;

	if (irq > CONFIG_NUM_IRQS) {
		return 0;
	}

	group = irq / MAX_REGISR_IRQ_NUM;
	index = irq % MAX_REGISR_IRQ_NUM;

	return IS_MASK_SET(IT8XXX2_INTC_IER(group), BIT(index));
}

uint8_t __soc_ram_code ite_intc_get_irq_num(void)
{
	return intc_irq;
}

bool __soc_ram_code ite_intc_no_irq(void)
{
	return (IVECT == IVECT_OFFSET_WITH_IRQ);
}

uint8_t __soc_ram_code get_irq(void *arg)
{
	ARG_UNUSED(arg);

	/* Wait until two equal interrupt values are read */
	do {
		/* Read interrupt number from interrupt vector register */
		intc_irq = IVECT;
		/*
		 * WORKAROUND: when the interrupt vector register (IVECT)
		 * isn't latched in a load operation, we read it again to make
		 * sure the value we got is the correct value.
		 */
	} while (intc_irq != IVECT);

	/* Determine interrupt number */
	intc_irq -= IVECT_OFFSET_WITH_IRQ;

	/*
	 * Look for pending interrupt if there's interrupt number 0 from
	 * the AIVECT register.
	 */
	if (intc_irq == 0) {
		uint8_t int_pending;

		for (int i = (IT8XXX2_INTC_GROUP_CNT - 1); i >= 0; i--) {
			int_pending =
				(IT8XXX2_INTC_ISR(i) & IT8XXX2_INTC_IER(i));
			if (int_pending != 0) {
				intc_irq = (MAX_REGISR_IRQ_NUM * i) +
						find_msb_set(int_pending) - 1;
				LOG_DBG("Pending interrupt found: %d",
						intc_irq);
				LOG_DBG("CPU mepc: 0x%lx", csr_read(mepc));
				break;
			}
		}
	}

	/* Clear interrupt status */
	ite_intc_isr_clear(intc_irq);

	/* Return interrupt number */
	return intc_irq;
}

void soc_interrupt_init(void)
{
	/* Ensure interrupts of soc are disabled at default */
	for (int i = 0; i < IT8XXX2_INTC_GROUP_CNT; i++) {
		IT8XXX2_INTC_IER(i) = 0;
	}

	/* Enable M-mode external interrupt */
	csr_set(mie, MIP_MEIP);
}
