/*
 * Copyright 2023 NXP
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include "test_shared_irq.h"

struct shared_irq_fixture {
	unsigned int irq1;
	unsigned int irq2;
	unsigned int irq1_table_idx;
	unsigned int irq2_table_idx;
	unsigned int irq_priority;
};

static struct shared_irq_fixture fixture;

static void reset_test_vector(void)
{
	int i;

	for (i = 0; i < TEST_VECTOR_SIZE; i++) {
		test_vector[i] = 0;
	}
}

static void dynamic_shared_irq_suite_after(void *data)
{
	ARG_UNUSED(data);

	/* note: no need to check the state of the SW ISR tables after
	 * all these disconnect operations. If there's something wrong
	 * it should be detected by dynamic_shared_irq_suite_before().
	 */
	arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority,
				    test_isr_0, 0, 0);
	arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority,
				    test_isr_1, (void *)1, 0);
	arch_irq_disconnect_dynamic(fixture.irq2, fixture.irq_priority,
				    test_isr_2, (void *)2, 0);
}

static void dummy_isr(const void *data)
{
	ARG_UNUSED(data);

	test_vector[0] = TEST_DUMMY_ISR_VAL;
}

static unsigned int get_irq_slot(unsigned int start)
{
	unsigned int i, table_idx;

	for (i = start; i <= CONFIG_GEN_IRQ_START_VECTOR + CONFIG_NUM_IRQS - 1; i++) {
		table_idx = i - CONFIG_GEN_IRQ_START_VECTOR;

		if (_sw_isr_table[table_idx].isr == &z_irq_spurious) {
			test_vector[0] = 0;

			/* check to see if we can trigger this IRQ */
			arch_irq_connect_dynamic(i, IRQ_PRIORITY, dummy_isr,
						 NULL, 0);
			irq_enable(i);
			trigger_irq(i);

			/* wait a bit */
			k_busy_wait(100);

			if (test_vector[0] == TEST_DUMMY_ISR_VAL) {
				/* found a valid INTID */
				irq_disable(i);

				arch_irq_disconnect_dynamic(i, IRQ_PRIORITY,
							    dummy_isr, NULL, 0);
				return i;
			}
		}
	}

	return TEST_INVALID_IRQ;
}

static void *dynamic_shared_irq_suite_setup(void)
{
	fixture.irq1 = get_irq_slot(CONFIG_GEN_IRQ_START_VECTOR);
	zassert_true(fixture.irq1 != TEST_INVALID_IRQ,
		     "no suitable value found for irq1");
	fixture.irq2 = get_irq_slot(fixture.irq1 + 1);
	zassert_true(fixture.irq2 != TEST_INVALID_IRQ,
		     "no suitable value found for irq2");
	fixture.irq_priority = IRQ_PRIORITY;

	fixture.irq1_table_idx = fixture.irq1 - CONFIG_GEN_IRQ_START_VECTOR;
	fixture.irq2_table_idx = fixture.irq2 - CONFIG_GEN_IRQ_START_VECTOR;

	return NULL;
}

static void dynamic_shared_irq_suite_before(void *data)
{
	ARG_UNUSED(data);

	arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority,
				 test_isr_0, 0, 0);

	zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_0,
		     "wrong _sw_isr_table ISR at irq1");
	zassert_true(!_sw_isr_table[fixture.irq1_table_idx].arg,
		     "wrong _sw_isr_table argument at irq1");
	zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num,
		     "wrong client number at irq1");

	arch_irq_connect_dynamic(fixture.irq1, fixture.irq_priority,
				 test_isr_1, (void *)1, 0);

	zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == z_shared_isr,
		     "wrong _sw_isr_table ISR at irq1");
	zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg ==
		     &z_shared_sw_isr_table[fixture.irq1_table_idx],
		     "wrong _sw_isr_table argument at irq1");
	zassert_true(z_shared_sw_isr_table[fixture.irq1_table_idx].client_num == 2,
		     "wrong client number at irq1");

	zassert_true(client_exists_at_index(test_isr_0, 0, fixture.irq1_table_idx, 0),
		     "unexpected client data for irq1, index 0");
	zassert_true(client_exists_at_index(test_isr_1, (void *)1, fixture.irq1_table_idx, 1),
		     "unexpected client data for irq1, index 1");

	arch_irq_connect_dynamic(fixture.irq2, fixture.irq_priority,
				 test_isr_2, (void *)2, 0);

	zassert_true(_sw_isr_table[fixture.irq2_table_idx].isr == test_isr_2,
		     "wrong _sw_isr_table ISR at irq2");
	zassert_true(_sw_isr_table[fixture.irq2_table_idx].arg == (void *)2,
		     "wrong _sw_isr_table argument at irq2");
	zassert_true(!z_shared_sw_isr_table[fixture.irq2_table_idx].client_num,
		     "wrong client number at irq2");

	reset_test_vector();
}

/**
 * @brief Test writing to a vector with a shared interrupt
 *
 * @ingroup kernel_interrupt_tests
 *
 * @details This tests if interrupts are dynamically shared successfully
 * (i.e: multiple ISR/arg pairs are called whenever the interrupt
 * they were registered for is triggered).
 */
ZTEST(shared_irq_feature, test_dynamic_shared_irq_write)
{
	int i;

	irq_enable(fixture.irq1);
	irq_enable(fixture.irq2);

	trigger_irq(fixture.irq1);
	trigger_irq(fixture.irq2);

	/* wait 5ms before checking the results */
	k_busy_wait(5000);

	for (i = 0; i < TEST_VECTOR_SIZE; i++) {
		zassert_true(test_vector[i] == result_vector[i],
			     "wrong test_vector value at %d: 0x%x vs 0x%x",
			     i, test_vector[i], result_vector[i]);
	}

	irq_disable(fixture.irq1);
	irq_disable(fixture.irq2);
}

/**
 * @brief Test writing to a vector after an ISR/arg disconnect.
 *
 * @ingroup kernel_interrupt_tests
 *
 * @details This tests if ISR/arg pairs are disconnected successfully
 * and the interrupts are "unshared" whenever a single ISR/arg pair is
 * left.
 */
ZTEST(shared_irq_feature, test_dynamic_shared_irq_disconnect_write)
{
	int i;

	/* remove test_isr_0/NULL pair. After this statement we expect
	 * irq1 to be unshared.
	 */
	arch_irq_disconnect_dynamic(fixture.irq1, fixture.irq_priority,
				    test_isr_0, 0, 0);

	zassert_true(_sw_isr_table[fixture.irq1_table_idx].isr == test_isr_1,
		     "wrong _sw_isr_table ISR at irq1");
	zassert_true(_sw_isr_table[fixture.irq1_table_idx].arg == (void *)1,
		     "wrong _sw_isr_table arg at irq1");
	zassert_true(!z_shared_sw_isr_table[fixture.irq1_table_idx].client_num,
		     "wrong client number at irq1");

	irq_enable(fixture.irq1);
	trigger_irq(fixture.irq1);

	/* wait 5ms before checking the results */
	k_busy_wait(5000);

	for (i = 0; i < TEST_VECTOR_SIZE; i++) {
		if (i == 1) {
			zassert_true(test_vector[i] == result_vector[i],
				     "wrong test_vector at %d: 0x%x vs 0x%x",
				     i, test_vector[i], result_vector[i]);
			continue;
		}

		zassert_true(!test_vector[i],
			     "wrong test_vector value at %d: 0x%x vs 0x%x",
			     i, test_vector[i], result_vector[i]);
	}

	irq_disable(fixture.irq1);
}

ZTEST_SUITE(shared_irq_feature, NULL,
	    dynamic_shared_irq_suite_setup,
	    dynamic_shared_irq_suite_before,
	    dynamic_shared_irq_suite_after,
	    NULL);
