/*
 * Verify PL031 functionality
 *
 * This test verifies whether the emulated PL031 behaves correctly.
 *
 * Copyright 2019 Amazon.com, Inc. or its affiliates.
 * Author: Alexander Graf <graf@amazon.com>
 *
 * This work is licensed under the terms of the GNU LGPL, version 2.
 */
#include <libcflat.h>
#include <devicetree.h>
#include <asm/processor.h>
#include <asm/io.h>
#include <asm/gic.h>

struct pl031_regs {
	uint32_t dr;	/* Data Register */
	uint32_t mr;	/* Match Register */
	uint32_t lr;	/* Load Register */
	union {
		uint8_t cr;	/* Control Register */
		uint32_t cr32;
	};
	union {
		uint8_t imsc;	/* Interrupt Mask Set or Clear register */
		uint32_t imsc32;
	};
	union {
		uint8_t ris;	/* Raw Interrupt Status */
		uint32_t ris32;
	};
	union {
		uint8_t mis;	/* Masked Interrupt Status */
		uint32_t mis32;
	};
	union {
		uint8_t icr;	/* Interrupt Clear Register */
		uint32_t icr32;
	};
	uint32_t reserved[1008];
	uint32_t periph_id[4];
	uint32_t pcell_id[4];
};

static u32 cntfrq;
static struct pl031_regs *pl031;
static int pl031_irq;
static void *gic_ispendr;
static volatile bool irq_triggered;

static int check_id(void)
{
	uint32_t id[] = { 0x31, 0x10, 0x14, 0x00, 0x0d, 0xf0, 0x05, 0xb1 };
	int i;

	for (i = 0; i < ARRAY_SIZE(id); i++)
		if (id[i] != readl(&pl031->periph_id[i]))
			return 1;

	return 0;
}

static int check_ro(void)
{
	uint32_t offs[] = { offsetof(struct pl031_regs, ris),
			    offsetof(struct pl031_regs, mis),
			    offsetof(struct pl031_regs, periph_id[0]),
			    offsetof(struct pl031_regs, periph_id[1]),
			    offsetof(struct pl031_regs, periph_id[2]),
			    offsetof(struct pl031_regs, periph_id[3]),
			    offsetof(struct pl031_regs, pcell_id[0]),
			    offsetof(struct pl031_regs, pcell_id[1]),
			    offsetof(struct pl031_regs, pcell_id[2]),
			    offsetof(struct pl031_regs, pcell_id[3]) };
	int i;

	for (i = 0; i < ARRAY_SIZE(offs); i++) {
		uint32_t before32;
		uint16_t before16;
		uint8_t before8;
		void *addr = (void*)pl031 + offs[i];
		uint32_t poison = 0xdeadbeefULL;

		before8 = readb(addr);
		before16 = readw(addr);
		before32 = readl(addr);

		writeb(poison, addr);
		writew(poison, addr);
		writel(poison, addr);

		if (before8 != readb(addr))
			return 1;
		if (before16 != readw(addr))
			return 1;
		if (before32 != readl(addr))
			return 1;
	}

	return 0;
}

static int check_rtc_freq(void)
{
	uint32_t seconds_to_wait = 2;
	uint32_t before = readl(&pl031->dr);
	uint64_t before_tick = get_cntvct();
	uint64_t target_tick = before_tick + (cntfrq * seconds_to_wait);

	/* Wait for 2 seconds */
	while (get_cntvct() < target_tick) ;

	if (readl(&pl031->dr) != before + seconds_to_wait)
		return 1;

	return 0;
}

static bool gic_irq_pending(void)
{
	uint32_t offset = (pl031_irq / 32) * 4;

	return readl(gic_ispendr + offset) & (1 << (pl031_irq & 31));
}

static void irq_handler(struct pt_regs *regs)
{
	u32 irqstat = gic_read_iar();
	u32 irqnr = gic_iar_irqnr(irqstat);

	gic_write_eoir(irqstat);

	if (irqnr == pl031_irq) {
		report(readl(&pl031->ris) == 1, "  RTC RIS == 1");
		report(readl(&pl031->mis) == 1, "  RTC MIS == 1");

		/* Writing one to bit zero should clear IRQ status */
		writel(1, &pl031->icr);

		report(readl(&pl031->ris) == 0, "  RTC RIS == 0");
		report(readl(&pl031->mis) == 0, "  RTC MIS == 0");
		irq_triggered = true;
	} else {
		report_info("Unexpected interrupt: %"PRIu32"\n", irqnr);
		return;
	}
}

static int check_rtc_irq(void)
{
	uint32_t seconds_to_wait = 1;
	uint32_t before = readl(&pl031->dr);
	uint64_t before_tick = get_cntvct();
	uint64_t target_tick = before_tick + (cntfrq * (seconds_to_wait + 1));

	report_info("Checking IRQ trigger (MR)");

	irq_triggered = false;

	/* Fire IRQ in 1 second */
	writel(before + seconds_to_wait, &pl031->mr);

#ifdef __aarch64__
	install_irq_handler(EL1H_IRQ, irq_handler);
#else
	install_exception_handler(EXCPTN_IRQ, irq_handler);
#endif

	/* Wait until 2 seconds are over */
	while (get_cntvct() < target_tick) ;

	report(!gic_irq_pending(), "  RTC IRQ not delivered without mask");

	/* Mask the IRQ so that it gets delivered */
	writel(1, &pl031->imsc);
	report(gic_irq_pending(), "  RTC IRQ pending now");

	/* Enable retrieval of IRQ */
	gic_enable_irq(pl031_irq);
	local_irq_enable();

	report(irq_triggered, "  IRQ triggered");
	report(!gic_irq_pending(), "  RTC IRQ not pending anymore");
	if (!irq_triggered) {
		report_info("  RTC RIS: %"PRIx32, readl(&pl031->ris));
		report_info("  RTC MIS: %"PRIx32, readl(&pl031->mis));
		report_info("  RTC IMSC: %"PRIx32, readl(&pl031->imsc));
		report_info("  GIC IRQs pending: %08"PRIx32" %08"PRIx32, readl(gic_ispendr), readl(gic_ispendr + 4));
	}

	local_irq_disable();
	return 0;
}

static void rtc_irq_init(void)
{
	gic_enable_defaults();

	switch (gic_version()) {
	case 2:
		gic_ispendr = gicv2_dist_base() + GICD_ISPENDR;
		break;
	case 3:
		gic_ispendr = gicv3_dist_base() + GICD_ISPENDR;
		break;
	}
}

static int rtc_fdt_init(void)
{
	const struct fdt_property *prop;
	const void *fdt = dt_fdt();
	struct dt_pbus_reg base;
	int node, len;
	u32 *data;
	int ret;

	node = fdt_node_offset_by_compatible(fdt, -1, "arm,pl031");
	if (node < 0)
		return -1;

	prop = fdt_get_property(fdt, node, "interrupts", &len);
	assert(prop && len == (3 * sizeof(u32)));
	data = (u32 *)prop->data;
	assert(data[0] == 0); /* SPI */
	pl031_irq = SPI(fdt32_to_cpu(data[1]));

	ret = dt_pbus_translate_node(node, 0, &base);
	assert(!ret);
	pl031 = ioremap(base.addr, base.size);

	return 0;
}

int main(int argc, char **argv)
{
	cntfrq = get_cntfrq();
	rtc_irq_init();
	if (rtc_fdt_init()) {
		report_skip("Skipping PL031 tests. No device present.");
		return 0;
	}

	report_prefix_push("pl031");
	report(!check_id(), "Periph/PCell IDs match");
	report(!check_ro(), "R/O fields are R/O");
	report(!check_rtc_freq(), "RTC ticks at 1HZ");
	report(!gic_irq_pending(), "RTC IRQ not pending yet");
	check_rtc_irq();

	return report_summary();
}
