/* SPDX-License-Identifier: GPL-2.0-only */

#include <acpi/acpi.h>
#include <arch/ioapic.h>
#include <arch/smp/mpspec.h>
#include <commonlib/sort.h>
#include <cpu/cpu.h>

static int acpi_create_madt_lapic(acpi_madt_lapic_t *lapic, u8 cpu, u8 apic)
{
	lapic->type = LOCAL_APIC; /* Local APIC structure */
	lapic->length = sizeof(acpi_madt_lapic_t);
	lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
	lapic->processor_id = cpu;
	lapic->apic_id = apic;

	return lapic->length;
}

static int acpi_create_madt_lx2apic(acpi_madt_lx2apic_t *lapic, u32 cpu, u32 apic)
{
	lapic->type = LOCAL_X2APIC; /* Local APIC structure */
	lapic->reserved = 0;
	lapic->length = sizeof(acpi_madt_lx2apic_t);
	lapic->flags = (1 << 0); /* Processor/LAPIC enabled */
	lapic->processor_id = cpu;
	lapic->x2apic_id = apic;

	return lapic->length;
}

unsigned long acpi_create_madt_one_lapic(unsigned long current, u32 index, u32 lapic_id)
{
	if (lapic_id <= ACPI_MADT_MAX_LAPIC_ID)
		current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, index,
						  lapic_id);
	else
		current += acpi_create_madt_lx2apic((acpi_madt_lx2apic_t *)current, index,
						    lapic_id);

	return current;
}

/* Increase if necessary. Currently all x86 CPUs only have 2 SMP threads */
#define MAX_THREAD_ID 1
/*
 * From ACPI 6.4 spec:
 * "The advent of multi-threaded processors yielded multiple logical processors
 * executing on common processor hardware. ACPI defines logical processors in
 * an identical manner as physical processors. To ensure that non
 * multi-threading aware OSPM implementations realize optimal performance on
 * platforms containing multi-threaded processors, two guidelines should be
 * followed. The first is the same as above, that is, OSPM should initialize
 * processors in the order that they appear in the MADT. The second is that
 * platform firmware should list the first logical processor of each of the
 * individual multi-threaded processors in the MADT before listing any of the
 * second logical processors. This approach should be used for all successive
 * logical processors."
 */
static unsigned long acpi_create_madt_lapics(unsigned long current)
{
	struct device *cpu;
	int index, apic_ids[CONFIG_MAX_CPUS] = {0}, num_cpus = 0, sort_start = 0;
	for (unsigned int thread_id = 0; thread_id <= MAX_THREAD_ID; thread_id++) {
		for (cpu = all_devices; cpu; cpu = cpu->next) {
			if (!is_enabled_cpu(cpu))
				continue;
			if (num_cpus >= ARRAY_SIZE(apic_ids))
				break;
			if (cpu->path.apic.thread_id != thread_id)
				continue;
			apic_ids[num_cpus++] = cpu->path.apic.apic_id;
		}
		bubblesort(&apic_ids[sort_start], num_cpus - sort_start, NUM_ASCENDING);
		sort_start = num_cpus;
	}
	for (index = 0; index < num_cpus; index++)
		current = acpi_create_madt_one_lapic(current, index, apic_ids[index]);

	return current;
}

static int acpi_create_madt_ioapic(acpi_madt_ioapic_t *ioapic, u8 id, u32 addr,
				u32 gsi_base)
{
	ioapic->type = IO_APIC; /* I/O APIC structure */
	ioapic->length = sizeof(acpi_madt_ioapic_t);
	ioapic->reserved = 0x00;
	ioapic->gsi_base = gsi_base;
	ioapic->ioapic_id = id;
	ioapic->ioapic_addr = addr;

	return ioapic->length;
}

/* For a system with multiple I/O APICs it's required that the one potentially
   routing i8259 via ExtNMI delivery calls this first to get GSI #0. */
int acpi_create_madt_ioapic_from_hw(acpi_madt_ioapic_t *ioapic, u32 addr)
{
	static u32 gsi_base;
	u32 my_base;
	u8 id = get_ioapic_id((void *)(uintptr_t)addr);
	u8 count = ioapic_get_max_vectors((void *)(uintptr_t)addr);

	my_base = gsi_base;
	gsi_base += count;
	return acpi_create_madt_ioapic(ioapic, id, addr, my_base);
}

static int acpi_create_madt_irqoverride(acpi_madt_irqoverride_t *irqoverride,
		u8 bus, u8 source, u32 gsirq, u16 flags)
{
	irqoverride->type = IRQ_SOURCE_OVERRIDE; /* Interrupt source override */
	irqoverride->length = sizeof(acpi_madt_irqoverride_t);
	irqoverride->bus = bus;
	irqoverride->source = source;
	irqoverride->gsirq = gsirq;
	irqoverride->flags = flags;

	return irqoverride->length;
}

static int acpi_create_madt_sci_override(acpi_madt_irqoverride_t *irqoverride)
{
	u8 gsi, irq, flags;

	ioapic_get_sci_pin(&gsi, &irq, &flags);

	if (!CONFIG(ACPI_HAVE_PCAT_8259))
		irq = gsi;

	irqoverride->type = IRQ_SOURCE_OVERRIDE; /* Interrupt source override */
	irqoverride->length = sizeof(acpi_madt_irqoverride_t);
	irqoverride->bus = MP_BUS_ISA;
	irqoverride->source = irq;
	irqoverride->gsirq = gsi;
	irqoverride->flags = flags;

	return irqoverride->length;
}

static unsigned long acpi_create_madt_ioapic_gsi0_default(unsigned long current)
{
	current += acpi_create_madt_ioapic_from_hw((acpi_madt_ioapic_t *)current, IO_APIC_ADDR);

	current += acpi_create_madt_irqoverride((void *)current, MP_BUS_ISA, 0, 2,
						MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH);

	current += acpi_create_madt_sci_override((void *)current);

	return current;
}

static int acpi_create_madt_lapic_nmi(acpi_madt_lapic_nmi_t *lapic_nmi, u8 cpu,
				u16 flags, u8 lint)
{
	lapic_nmi->type = LOCAL_APIC_NMI; /* Local APIC NMI structure */
	lapic_nmi->length = sizeof(acpi_madt_lapic_nmi_t);
	lapic_nmi->flags = flags;
	lapic_nmi->processor_id = cpu;
	lapic_nmi->lint = lint;

	return lapic_nmi->length;
}

static int acpi_create_madt_lx2apic_nmi(acpi_madt_lx2apic_nmi_t *lapic_nmi, u32 cpu,
				 u16 flags, u8 lint)
{
	lapic_nmi->type = LOCAL_X2APIC_NMI; /* Local APIC NMI structure */
	lapic_nmi->length = sizeof(acpi_madt_lx2apic_nmi_t);
	lapic_nmi->flags = flags;
	lapic_nmi->processor_id = cpu;
	lapic_nmi->lint = lint;
	lapic_nmi->reserved[0] = 0;
	lapic_nmi->reserved[1] = 0;
	lapic_nmi->reserved[2] = 0;

	return lapic_nmi->length;
}

unsigned long acpi_create_madt_lapic_nmis(unsigned long current)
{
	const u16 flags = MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH;

	/* 1: LINT1 connect to NMI */
	/* create all subtables for processors */
	current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *)current,
			ACPI_MADT_LAPIC_NMI_ALL_PROCESSORS, flags, 1);

	if (!CONFIG(XAPIC_ONLY))
		current += acpi_create_madt_lx2apic_nmi((acpi_madt_lx2apic_nmi_t *)current,
			ACPI_MADT_LX2APIC_NMI_ALL_PROCESSORS, flags, 1);

	return current;
}

static unsigned long acpi_create_madt_lapics_with_nmis(unsigned long current)
{
	current = acpi_create_madt_lapics(current);
	current = acpi_create_madt_lapic_nmis(current);
	return current;
}

int acpi_create_srat_lapic(acpi_srat_lapic_t *lapic, u8 node, u8 apic)
{
	memset((void *)lapic, 0, sizeof(acpi_srat_lapic_t));

	lapic->type = 0; /* Processor local APIC/SAPIC affinity structure */
	lapic->length = sizeof(acpi_srat_lapic_t);
	lapic->flags = (1 << 0); /* Enabled (the use of this structure). */
	lapic->proximity_domain_7_0 = node;
	/* TODO: proximity_domain_31_8, local SAPIC EID, clock domain. */
	lapic->apic_id = apic;

	return lapic->length;
}

int acpi_create_srat_x2apic(acpi_srat_x2apic_t *x2apic, u32 node, u32 apic)
{
	memset((void *)x2apic, 0, sizeof(acpi_srat_x2apic_t));

	x2apic->type = 2; /* Processor x2APIC structure */
	x2apic->length = sizeof(acpi_srat_x2apic_t);
	x2apic->flags = (1 << 0); /* Enabled (the use of this structure). */
	x2apic->proximity_domain = node;
	x2apic->x2apic_id = apic;

	return x2apic->length;
}

unsigned long acpi_arch_fill_madt(acpi_madt_t *madt, unsigned long current)
{
	madt->lapic_addr = cpu_get_lapic_addr();

	if (CONFIG(ACPI_HAVE_PCAT_8259))
		madt->flags |= 1;

	if (CONFIG(ACPI_COMMON_MADT_LAPIC))
		current = acpi_create_madt_lapics_with_nmis(current);

	if (CONFIG(ACPI_COMMON_MADT_IOAPIC))
		current = acpi_create_madt_ioapic_gsi0_default(current);

	return current;
}
