/*
 * Copyright (c) 2016 Open-RnD Sp. z o.o.
 * Copyright (c) 2017 RnDity Sp. z o.o.
 * Copyright (c) 2019-23 Linaro Limited
 *
 * SPDX-License-Identifier: Apache-2.0
 */

/**
 * @brief Driver for External interrupt/event controller in STM32 MCUs
 */

#define EXTI_NODE DT_INST(0, st_stm32_exti)

#include <zephyr/device.h>
#include <soc.h>
#include <stm32_ll_exti.h>
#include <zephyr/sys/__assert.h>
#include <zephyr/sys/util.h>
#include <zephyr/drivers/interrupt_controller/exti_stm32.h>
#include <zephyr/irq.h>

#include "stm32_hsem.h"

/** @brief EXTI line ranges hold by a single ISR */
struct stm32_exti_range {
	/** Start of the range */
	uint8_t start;
	/** Range length */
	uint8_t len;
};

#define NUM_EXTI_LINES DT_PROP(DT_NODELABEL(exti), num_lines)

static IRQn_Type exti_irq_table[NUM_EXTI_LINES] = {[0 ... NUM_EXTI_LINES - 1] = 0xFF};

/* wrapper for user callback */
struct __exti_cb {
	stm32_exti_callback_t cb;
	void *data;
};

/* driver data */
struct stm32_exti_data {
	/* per-line callbacks */
	struct __exti_cb cb[NUM_EXTI_LINES];
};

void stm32_exti_enable(int line)
{
	int irqnum = 0;

	if (line >= NUM_EXTI_LINES) {
		__ASSERT_NO_MSG(line);
	}

	/* Get matching exti irq provided line thanks to irq_table */
	irqnum = exti_irq_table[line];
	if (irqnum == 0xFF) {
		__ASSERT_NO_MSG(line);
	}

	/* Enable requested line interrupt */
#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
	LL_C2_EXTI_EnableIT_0_31(BIT((uint32_t)line));
#else
	LL_EXTI_EnableIT_0_31(BIT((uint32_t)line));
#endif

	/* Enable exti irq interrupt */
	irq_enable(irqnum);
}

void stm32_exti_disable(int line)
{
	z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);

	if (line < 32) {
#if defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
		LL_C2_EXTI_DisableIT_0_31(BIT((uint32_t)line));
#else
		LL_EXTI_DisableIT_0_31(BIT((uint32_t)line));
#endif
	} else {
		__ASSERT_NO_MSG(line);
	}
	z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
}

/**
 * @brief check if interrupt is pending
 *
 * @param line line number
 */
static inline int stm32_exti_is_pending(int line)
{
	if (line < 32) {
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
		return (LL_EXTI_IsActiveRisingFlag_0_31(BIT((uint32_t)line)) ||
			LL_EXTI_IsActiveFallingFlag_0_31(BIT((uint32_t)line)));
#elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
		return LL_C2_EXTI_IsActiveFlag_0_31(BIT((uint32_t)line));
#else
		return LL_EXTI_IsActiveFlag_0_31(BIT((uint32_t)line));
#endif
	} else {
		__ASSERT_NO_MSG(line);
		return 0;
	}
}

/**
 * @brief clear pending interrupt bit
 *
 * @param line line number
 */
static inline void stm32_exti_clear_pending(int line)
{
	if (line < 32) {
#if DT_HAS_COMPAT_STATUS_OKAY(st_stm32g0_exti)
		LL_EXTI_ClearRisingFlag_0_31(BIT((uint32_t)line));
		LL_EXTI_ClearFallingFlag_0_31(BIT((uint32_t)line));
#elif defined(CONFIG_SOC_SERIES_STM32H7X) && defined(CONFIG_CPU_CORTEX_M4)
		LL_C2_EXTI_ClearFlag_0_31(BIT((uint32_t)line));
#else
		LL_EXTI_ClearFlag_0_31(BIT((uint32_t)line));
#endif
	} else {
		__ASSERT_NO_MSG(line);
	}
}

void stm32_exti_trigger(int line, int trigger)
{

	if (line >= 32) {
		__ASSERT_NO_MSG(line);
	}

	z_stm32_hsem_lock(CFG_HW_EXTI_SEMID, HSEM_LOCK_DEFAULT_RETRY);

	switch (trigger) {
	case STM32_EXTI_TRIG_NONE:
		LL_EXTI_DisableRisingTrig_0_31(BIT((uint32_t)line));
		LL_EXTI_DisableFallingTrig_0_31(BIT((uint32_t)line));
		break;
	case STM32_EXTI_TRIG_RISING:
		LL_EXTI_EnableRisingTrig_0_31(BIT((uint32_t)line));
		LL_EXTI_DisableFallingTrig_0_31(BIT((uint32_t)line));
		break;
	case STM32_EXTI_TRIG_FALLING:
		LL_EXTI_EnableFallingTrig_0_31(BIT((uint32_t)line));
		LL_EXTI_DisableRisingTrig_0_31(BIT((uint32_t)line));
		break;
	case STM32_EXTI_TRIG_BOTH:
		LL_EXTI_EnableRisingTrig_0_31(BIT((uint32_t)line));
		LL_EXTI_EnableFallingTrig_0_31(BIT((uint32_t)line));
		break;
	default:
		__ASSERT_NO_MSG(trigger);
		break;
	}
	z_stm32_hsem_unlock(CFG_HW_EXTI_SEMID);
}

/**
 * @brief EXTI ISR handler
 *
 * Check EXTI lines in exti_range for pending interrupts
 *
 * @param *exti_range Pointer to a exti_range structure
 */
static void stm32_exti_isr(const void *exti_range)
{
	const struct device *dev = DEVICE_DT_GET(EXTI_NODE);
	struct stm32_exti_data *data = dev->data;
	const struct stm32_exti_range *range = exti_range;
	int line;

	/* see which bits are set */
	for (uint8_t i = 0; i <= range->len; i++) {
		line = range->start + i;
		/* check if interrupt is pending */
		if (stm32_exti_is_pending(line) != 0) {
			/* clear pending interrupt */
			stm32_exti_clear_pending(line);

			/* run callback only if one is registered */
			if (!data->cb[line].cb) {
				continue;
			}

			data->cb[line].cb(line, data->cb[line].data);
		}
	}
}

static void stm32_fill_irq_table(int8_t start, int8_t len, int32_t irqn)
{
	for (int i = 0; i < len; i++) {
		exti_irq_table[start + i] = irqn;
	}
}

/* This macro:
 * - populates line_range_x from line_range dt property
 * - fill exti_irq_table through stm32_fill_irq_table()
 * - calls IRQ_CONNECT for each irq & matching line_range
 */

#define STM32_EXTI_INIT(node_id, interrupts, idx)			\
	static const struct stm32_exti_range line_range_##idx = {	\
		DT_PROP_BY_IDX(node_id, line_ranges, UTIL_X2(idx)),	      \
		DT_PROP_BY_IDX(node_id, line_ranges, UTIL_INC(UTIL_X2(idx))) \
	};								\
	stm32_fill_irq_table(line_range_##idx.start,			\
			     line_range_##idx.len,			\
			     DT_IRQ_BY_IDX(node_id, idx, irq));		\
	IRQ_CONNECT(DT_IRQ_BY_IDX(node_id, idx, irq),			\
		DT_IRQ_BY_IDX(node_id, idx, priority),			\
		stm32_exti_isr, &line_range_##idx,			\
		0);

/**
 * @brief initialize EXTI device driver
 */
static int stm32_exti_init(const struct device *dev)
{
	ARG_UNUSED(dev);

	DT_FOREACH_PROP_ELEM(DT_NODELABEL(exti),
			     interrupt_names,
			     STM32_EXTI_INIT);

	return 0;
}

static struct stm32_exti_data exti_data;
DEVICE_DT_DEFINE(EXTI_NODE, &stm32_exti_init,
		 NULL,
		 &exti_data, NULL,
		 PRE_KERNEL_1, CONFIG_INTC_INIT_PRIORITY,
		 NULL);

/**
 * @brief set & unset for the interrupt callbacks
 */
int stm32_exti_set_callback(int line, stm32_exti_callback_t cb, void *arg)
{
	const struct device *const dev = DEVICE_DT_GET(EXTI_NODE);
	struct stm32_exti_data *data = dev->data;

	if ((data->cb[line].cb == cb) && (data->cb[line].data == arg)) {
		return 0;
	}

	/* if callback already exists/maybe-running return busy */
	if (data->cb[line].cb != NULL) {
		return -EBUSY;
	}

	data->cb[line].cb = cb;
	data->cb[line].data = arg;

	return 0;
}

void stm32_exti_unset_callback(int line)
{
	const struct device *const dev = DEVICE_DT_GET(EXTI_NODE);
	struct stm32_exti_data *data = dev->data;

	data->cb[line].cb = NULL;
	data->cb[line].data = NULL;
}
