/*
 * 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 void *gic_isenabler;
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 gic_irq_unmask(void)
{
	uint32_t offset = (pl031_irq / 32) * 4;

	writel(1 << (pl031_irq & 31), gic_isenabler + offset);
}

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: %d\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_irq_unmask();
	local_irq_enable();

	report(irq_triggered, "  IRQ triggered");
	report(!gic_irq_pending(), "  RTC IRQ not pending anymore");
	if (!irq_triggered) {
		report_info("  RTC RIS: %x", readl(&pl031->ris));
		report_info("  RTC MIS: %x", readl(&pl031->mis));
		report_info("  RTC IMSC: %x", readl(&pl031->imsc));
		report_info("  GIC IRQs pending: %08x %08x", 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;
		gic_isenabler = gicv2_dist_base() + GICD_ISENABLER;
		break;
	case 3:
		gic_ispendr = gicv3_dist_base() + GICD_ISPENDR;
		gic_isenabler = gicv3_dist_base() + GICD_ISENABLER;
		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();
}
