// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
 *
 * Part of this file is ported from coreboot src/arch/x86/boot/pirq_routing.c
 */

#include <common.h>
#include <pci.h>
#include <asm/pci.h>
#include <asm/pirq_routing.h>

static u8 pirq_get_next_free_irq(struct udevice *dev, u8 *pirq, u16 bitmap,
				 bool irq_already_routed[])
{
	int i, link;
	u8 irq = 0;

	/* IRQ sharing starts from IRQ#3 */
	for (i = 3; i < 16; i++) {
		/* Can we assign this IRQ? */
		if (!((bitmap >> i) & 1))
			continue;

		/* We can, now let's assume we can use this IRQ */
		irq = i;

		/* Have we already routed it? */
		if (irq_already_routed[irq])
			continue;

		for (link = 0; link < CONFIG_MAX_PIRQ_LINKS; link++) {
			if (pirq_check_irq_routed(dev, link, irq)) {
				irq_already_routed[irq] = true;
				break;
			}
		}

		/* If it's not yet routed, use it */
		if (!irq_already_routed[irq]) {
			irq_already_routed[irq] = true;
			break;
		}

		/* But if it was already routed, try the next one */
	}

	/* Now we get our IRQ */
	return irq;
}

void pirq_route_irqs(struct udevice *dev, struct irq_info *irq, int num)
{
	unsigned char irq_slot[MAX_INTX_ENTRIES];
	unsigned char pirq[CONFIG_MAX_PIRQ_LINKS];
	bool irq_already_routed[16];
	int i, intx;

	memset(pirq, 0, CONFIG_MAX_PIRQ_LINKS);
	memset(irq_already_routed, '\0', sizeof(irq_already_routed));

	/* Set PCI IRQs */
	for (i = 0; i < num; i++) {
		debug("PIRQ Entry %d Dev: %d.%x.%d\n", i,
		      irq->bus, irq->devfn >> 3, irq->devfn & 7);

		for (intx = 0; intx < MAX_INTX_ENTRIES; intx++) {
			int link = irq->irq[intx].link;
			int bitmap = irq->irq[intx].bitmap;
			int irq = 0;

			debug("INT%c link: %x bitmap: %x ",
			      'A' + intx, link, bitmap);

			if (!bitmap || !link) {
				debug("not routed\n");
				irq_slot[intx] = irq;
				continue;
			}

			/* translate link value to link number */
			link = pirq_translate_link(dev, link);

			/* yet not routed */
			if (!pirq[link]) {
				irq = pirq_get_next_free_irq(dev, pirq, bitmap,
						irq_already_routed);
				pirq[link] = irq;
			} else {
				irq = pirq[link];
			}

			debug("IRQ: %d\n", irq);
			irq_slot[intx] = irq;

			/* Assign IRQ in the interrupt router */
			pirq_assign_irq(dev, link, irq);
		}

		/* Bus, device, slots IRQs for {A,B,C,D} */
		pci_assign_irqs(irq->bus, irq->devfn >> 3, irq_slot);

		irq++;
	}

	for (i = 0; i < CONFIG_MAX_PIRQ_LINKS; i++)
		debug("PIRQ%c: %d\n", 'A' + i, pirq[i]);
}

u32 copy_pirq_routing_table(u32 addr, struct irq_routing_table *rt)
{
	struct irq_routing_table *rom_rt;

	/* Align the table to be 16 byte aligned */
	addr = ALIGN(addr, 16);

	debug("Copying Interrupt Routing Table to 0x%x\n", addr);
	memcpy((void *)(uintptr_t)addr, rt, rt->size);

	/*
	 * We do the sanity check here against the copied table after memcpy,
	 * as something might go wrong after the memcpy, which is normally
	 * due to the F segment decode is not turned on to systeam RAM.
	 */
	rom_rt = (struct irq_routing_table *)(uintptr_t)addr;
	if (rom_rt->signature != PIRQ_SIGNATURE ||
	    rom_rt->version != PIRQ_VERSION || rom_rt->size % 16) {
		printf("Interrupt Routing Table not valid\n");
		return addr;
	}

	return addr + rt->size;
}
