/*
 * Copyright (c) 2021 BayLibre, SAS
 *
 * SPDX-License-Identifier: Apache-2.0
 */

#include <ztest.h>
#include <zephyr/device.h>
#include <zephyr/drivers/interrupt_controller/gicv3_its.h>

#define DT_DRV_COMPAT   arm_gic_v3_its

static volatile unsigned int last_lpi_irq_num;

static void lpi_irq_handle(const void *parameter)
{
	uintptr_t i = (uintptr_t)parameter;

	last_lpi_irq_num = i;
}

/* Generate a DeviceID over the whole 16bits */
#define ITS_TEST_DEV(id)        ((((id + 256) % 16) << 12) | (((id + 256) % 24) << 8) | (id & 0xff))

/* Cover up to 8192 LPIs over 256 DevicesIDs and 32 EventIDs per DeviceID */
#define ITS_TEST_NUM_DEVS       256
#define ITS_TEST_NUM_ITES       32

/* Do not test all 8192 irqs, iterate with a prime offset to cover most of the possible event_ids */
#define ITS_TEST_NEXT		13

/* Active-wait loops waiting for an interrupt */
#define ITS_TEST_LOOPS		10

unsigned int vectors[ITS_TEST_NUM_DEVS][ITS_TEST_NUM_ITES];

static void test_gicv3_its_alloc(void)
{
	int devn, event_id;
	const struct device *dev = DEVICE_DT_INST_GET(0);

	zassert_false(dev == NULL, "");

	for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
		int device_id = ITS_TEST_DEV(devn);

		zassert_true(its_setup_deviceid(dev, device_id, ITS_TEST_NUM_ITES) == 0, "");

		for (event_id = 0; event_id < ITS_TEST_NUM_ITES; ++event_id) {
			vectors[devn][event_id] = its_alloc_intid(dev);
			zassert_true(vectors[devn][event_id] >= 8192, "");
			zassert_true(vectors[devn][event_id] < CONFIG_NUM_IRQS, "");

			zassert_true(its_map_intid(dev, device_id, event_id,
						   vectors[devn][event_id]) == 0, "");
		}
	}
}

static void test_gicv3_its_connect(void)
{
	int devn, event_id;
	const struct device *dev = DEVICE_DT_INST_GET(0);
	unsigned int remain = 0;

	zassert_false(dev == NULL, "");

	for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
		for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) {
			unsigned int irqn = vectors[devn][event_id];

			zassert_true(irq_connect_dynamic(irqn, 0, lpi_irq_handle,
							 (void *)(uintptr_t)(irqn), 0) == irqn, "");

			irq_enable(irqn);
		}
		remain = event_id - ITS_TEST_NUM_ITES;
	}
}

static void test_gicv3_its_irq_simple(void)
{
	const struct device *dev = DEVICE_DT_INST_GET(0);
	unsigned int irqn = vectors[0][0];
	unsigned int timeout;
	int device_id = ITS_TEST_DEV(0);
	int event_id = 0;

	zassert_false(dev == NULL, "");

	last_lpi_irq_num = 0;
	zassert_true(its_send_int(dev, device_id, event_id) == 0, "");

	timeout = ITS_TEST_LOOPS;
	while (!last_lpi_irq_num && timeout) {
		timeout--;
	}

	zassert_true(last_lpi_irq_num == irqn,
			"IRQ %d of DeviceID %x EventID %d failed",
			irqn, device_id, event_id);
}

static void test_gicv3_its_irq_disable(void)
{
	const struct device *dev = DEVICE_DT_INST_GET(0);
	unsigned int irqn = vectors[0][0];
	unsigned int timeout;
	int device_id = ITS_TEST_DEV(0);
	int event_id = 0;

	zassert_false(dev == NULL, "");

	irq_disable(irqn);

	last_lpi_irq_num = 0;
	zassert_true(its_send_int(dev, device_id, event_id) == 0, "");

	timeout = ITS_TEST_LOOPS;
	while (!last_lpi_irq_num && timeout) {
		timeout--;
	}

	zassert_true(last_lpi_irq_num == 0,
			"IRQ %d of DeviceID %x EventID %d disable failed",
			irqn, device_id, event_id);

	irq_enable(irqn);

	last_lpi_irq_num = 0;
	zassert_true(its_send_int(dev, device_id, event_id) == 0, "");

	timeout = ITS_TEST_LOOPS;
	while (!last_lpi_irq_num && timeout) {
		timeout--;
	}

	zassert_true(last_lpi_irq_num == irqn,
			"IRQ %d of DeviceID %x EventID %d re-enable failed",
			irqn, device_id, event_id);
}

static void test_gicv3_its_irq(void)
{
	int devn, event_id;
	const struct device *dev = DEVICE_DT_INST_GET(0);
	unsigned int timeout;
	unsigned int remain = 0;

	zassert_false(dev == NULL, "");

	for (devn = 0; devn < ITS_TEST_NUM_DEVS; ++devn) {
		int device_id = ITS_TEST_DEV(devn);

		for (event_id = remain; event_id < ITS_TEST_NUM_ITES; event_id += ITS_TEST_NEXT) {
			unsigned int irqn = vectors[devn][event_id];

			last_lpi_irq_num = 0;
			zassert_true(its_send_int(dev, device_id, event_id) == 0, "");

			timeout = ITS_TEST_LOOPS;
			while (!last_lpi_irq_num && timeout) {
				timeout--;
			}

			zassert_true(last_lpi_irq_num == irqn,
				     "IRQ %d of DeviceID %x EventID %d failed",
				     irqn, device_id, event_id);
		}

		remain = event_id - ITS_TEST_NUM_ITES;
	}
}

void test_main(void)
{
	ztest_test_suite(its_func,
			 ztest_unit_test(test_gicv3_its_alloc),
			 ztest_unit_test(test_gicv3_its_connect),
			 ztest_unit_test(test_gicv3_its_irq_simple),
			 ztest_unit_test(test_gicv3_its_irq_disable),
			 ztest_unit_test(test_gicv3_its_irq));
	ztest_run_test_suite(its_func);
}
