/* 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;
}

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;
}

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;
}
