// SPDX-License-Identifier: GPL-2.0+
/*
 * Copyright (C) 2015, Bin Meng <bmeng.cn@gmail.com>
 */

#include <common.h>
#include <dm.h>
#include <errno.h>
#include <fdtdec.h>
#include <malloc.h>
#include <asm/io.h>
#include <asm/irq.h>
#include <asm/pci.h>
#include <asm/pirq_routing.h>
#include <asm/tables.h>

DECLARE_GLOBAL_DATA_PTR;

bool pirq_check_irq_routed(struct udevice *dev, int link, u8 irq)
{
	struct irq_router *priv = dev_get_priv(dev);
	u8 pirq;
	int base = priv->link_base;

	if (priv->config == PIRQ_VIA_PCI)
		dm_pci_read_config8(dev->parent, LINK_N2V(link, base), &pirq);
	else
		pirq = readb((uintptr_t)priv->ibase + LINK_N2V(link, base));

	pirq &= 0xf;

	/* IRQ# 0/1/2/8/13 are reserved */
	if (pirq < 3 || pirq == 8 || pirq == 13)
		return false;

	return pirq == irq ? true : false;
}

int pirq_translate_link(struct udevice *dev, int link)
{
	struct irq_router *priv = dev_get_priv(dev);

	return LINK_V2N(link, priv->link_base);
}

void pirq_assign_irq(struct udevice *dev, int link, u8 irq)
{
	struct irq_router *priv = dev_get_priv(dev);
	int base = priv->link_base;

	/* IRQ# 0/1/2/8/13 are reserved */
	if (irq < 3 || irq == 8 || irq == 13)
		return;

	if (priv->config == PIRQ_VIA_PCI)
		dm_pci_write_config8(dev->parent, LINK_N2V(link, base), irq);
	else
		writeb(irq, (uintptr_t)priv->ibase + LINK_N2V(link, base));
}

static struct irq_info *check_dup_entry(struct irq_info *slot_base,
					int entry_num, int bus, int device)
{
	struct irq_info *slot = slot_base;
	int i;

	for (i = 0; i < entry_num; i++) {
		if (slot->bus == bus && slot->devfn == (device << 3))
			break;
		slot++;
	}

	return (i == entry_num) ? NULL : slot;
}

static inline void fill_irq_info(struct irq_router *priv, struct irq_info *slot,
				 int bus, int device, int pin, int pirq)
{
	slot->bus = bus;
	slot->devfn = (device << 3) | 0;
	slot->irq[pin - 1].link = LINK_N2V(pirq, priv->link_base);
	slot->irq[pin - 1].bitmap = priv->irq_mask;
}

static int create_pirq_routing_table(struct udevice *dev)
{
	struct irq_router *priv = dev_get_priv(dev);
	const void *blob = gd->fdt_blob;
	int node;
	int len, count;
	const u32 *cell;
	struct irq_routing_table *rt;
	struct irq_info *slot, *slot_base;
	int irq_entries = 0;
	int i;
	int ret;

	node = dev_of_offset(dev);

	/* extract the bdf from fdt_pci_addr */
	priv->bdf = dm_pci_get_bdf(dev->parent);

	ret = fdt_stringlist_search(blob, node, "intel,pirq-config", "pci");
	if (!ret) {
		priv->config = PIRQ_VIA_PCI;
	} else {
		ret = fdt_stringlist_search(blob, node, "intel,pirq-config",
					    "ibase");
		if (!ret)
			priv->config = PIRQ_VIA_IBASE;
		else
			return -EINVAL;
	}

	ret = fdtdec_get_int(blob, node, "intel,pirq-link", -1);
	if (ret == -1)
		return ret;
	priv->link_base = ret;

	priv->irq_mask = fdtdec_get_int(blob, node,
					"intel,pirq-mask", PIRQ_BITMAP);

	if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE)) {
		/* Reserve IRQ9 for SCI */
		priv->irq_mask &= ~(1 << 9);
	}

	if (priv->config == PIRQ_VIA_IBASE) {
		int ibase_off;

		ibase_off = fdtdec_get_int(blob, node, "intel,ibase-offset", 0);
		if (!ibase_off)
			return -EINVAL;

		/*
		 * Here we assume that the IBASE register has already been
		 * properly configured by U-Boot before.
		 *
		 * By 'valid' we mean:
		 *   1) a valid memory space carved within system memory space
		 *      assigned to IBASE register block.
		 *   2) memory range decoding is enabled.
		 * Hence we don't do any santify test here.
		 */
		dm_pci_read_config32(dev->parent, ibase_off, &priv->ibase);
		priv->ibase &= ~0xf;
	}

	priv->actl_8bit = fdtdec_get_bool(blob, node, "intel,actl-8bit");
	priv->actl_addr = fdtdec_get_int(blob, node, "intel,actl-addr", 0);

	cell = fdt_getprop(blob, node, "intel,pirq-routing", &len);
	if (!cell || len % sizeof(struct pirq_routing))
		return -EINVAL;
	count = len / sizeof(struct pirq_routing);

	rt = calloc(1, sizeof(struct irq_routing_table));
	if (!rt)
		return -ENOMEM;

	/* Populate the PIRQ table fields */
	rt->signature = PIRQ_SIGNATURE;
	rt->version = PIRQ_VERSION;
	rt->rtr_bus = PCI_BUS(priv->bdf);
	rt->rtr_devfn = (PCI_DEV(priv->bdf) << 3) | PCI_FUNC(priv->bdf);
	rt->rtr_vendor = PCI_VENDOR_ID_INTEL;
	rt->rtr_device = PCI_DEVICE_ID_INTEL_ICH7_31;

	slot_base = rt->slots;

	/* Now fill in the irq_info entries in the PIRQ table */
	for (i = 0; i < count;
	     i++, cell += sizeof(struct pirq_routing) / sizeof(u32)) {
		struct pirq_routing pr;

		pr.bdf = fdt_addr_to_cpu(cell[0]);
		pr.pin = fdt_addr_to_cpu(cell[1]);
		pr.pirq = fdt_addr_to_cpu(cell[2]);

		debug("irq_info %d: b.d.f %x.%x.%x INT%c PIRQ%c\n",
		      i, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
		      PCI_FUNC(pr.bdf), 'A' + pr.pin - 1,
		      'A' + pr.pirq);

		slot = check_dup_entry(slot_base, irq_entries,
				       PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));
		if (slot) {
			debug("found entry for bus %d device %d, ",
			      PCI_BUS(pr.bdf), PCI_DEV(pr.bdf));

			if (slot->irq[pr.pin - 1].link) {
				debug("skipping\n");

				/*
				 * Sanity test on the routed PIRQ pin
				 *
				 * If they don't match, show a warning to tell
				 * there might be something wrong with the PIRQ
				 * routing information in the device tree.
				 */
				if (slot->irq[pr.pin - 1].link !=
					LINK_N2V(pr.pirq, priv->link_base))
					debug("WARNING: Inconsistent PIRQ routing information\n");
				continue;
			}
		} else {
			slot = slot_base + irq_entries++;
		}
		debug("writing INT%c\n", 'A' + pr.pin - 1);
		fill_irq_info(priv, slot, PCI_BUS(pr.bdf), PCI_DEV(pr.bdf),
			      pr.pin, pr.pirq);
	}

	rt->size = irq_entries * sizeof(struct irq_info) + 32;

	/* Fix up the table checksum */
	rt->checksum = table_compute_checksum(rt, rt->size);

	gd->arch.pirq_routing_table = rt;

	return 0;
}

static void irq_enable_sci(struct udevice *dev)
{
	struct irq_router *priv = dev_get_priv(dev);

	if (priv->actl_8bit) {
		/* Bit7 must be turned on to enable ACPI */
		dm_pci_write_config8(dev->parent, priv->actl_addr, 0x80);
	} else {
		/* Write 0 to enable SCI on IRQ9 */
		if (priv->config == PIRQ_VIA_PCI)
			dm_pci_write_config32(dev->parent, priv->actl_addr, 0);
		else
			writel(0, (uintptr_t)priv->ibase + priv->actl_addr);
	}
}

int irq_router_common_init(struct udevice *dev)
{
	int ret;

	ret = create_pirq_routing_table(dev);
	if (ret) {
		debug("Failed to create pirq routing table\n");
		return ret;
	}
	/* Route PIRQ */
	pirq_route_irqs(dev, gd->arch.pirq_routing_table->slots,
			get_irq_slot_count(gd->arch.pirq_routing_table));

	if (IS_ENABLED(CONFIG_GENERATE_ACPI_TABLE))
		irq_enable_sci(dev);

	return 0;
}

int irq_router_probe(struct udevice *dev)
{
	return irq_router_common_init(dev);
}

ulong write_pirq_routing_table(ulong addr)
{
	if (!gd->arch.pirq_routing_table)
		return addr;

	return copy_pirq_routing_table(addr, gd->arch.pirq_routing_table);
}

static const struct udevice_id irq_router_ids[] = {
	{ .compatible = "intel,irq-router" },
	{ }
};

U_BOOT_DRIVER(irq_router_drv) = {
	.name		= "intel_irq",
	.id		= UCLASS_IRQ,
	.of_match	= irq_router_ids,
	.probe		= irq_router_probe,
	.priv_auto_alloc_size = sizeof(struct irq_router),
};

UCLASS_DRIVER(irq) = {
	.id		= UCLASS_IRQ,
	.name		= "irq",
};
