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

/*
 * This file is created based on Intel Alder Lake Processor SA Datasheet
 * Document number: 619503
 * Chapter number: 3
 */

#include <arch/ioapic.h>
#include <console/console.h>
#include <cpu/x86/msr.h>
#include <device/device.h>
#include <device/pci.h>
#include <delay.h>
#include <intelblocks/cpulib.h>
#include <intelblocks/msr.h>
#include <intelblocks/power_limit.h>
#include <intelblocks/systemagent.h>
#include <soc/iomap.h>
#include <soc/soc_chip.h>
#include <soc/systemagent.h>
#include <spi_flash.h>
#include "stddef.h"

/*
 * SoC implementation
 *
 * Add all known fixed memory ranges for Host Controller/Memory
 * controller.
 */
void soc_add_fixed_mmio_resources(struct device *dev, int *index)
{
	static const struct sa_mmio_descriptor soc_fixed_resources[] = {
		{ MCHBAR, MCH_BASE_ADDRESS, MCH_BASE_SIZE, "MCHBAR" },
		{ DMIBAR, DMI_BASE_ADDRESS, DMI_BASE_SIZE, "DMIBAR" },
		{ EPBAR, EP_BASE_ADDRESS, EP_BASE_SIZE, "EPBAR" },
		{ REGBAR, REG_BASE_ADDRESS, REG_BASE_SIZE, "REGBAR" },
		{ EDRAMBAR, EDRAM_BASE_ADDRESS, EDRAM_BASE_SIZE, "EDRAMBAR" },

		/* first field (sa_mmio_descriptor.index) is not used, setting to 0: */
		{ 0, CRAB_ABORT_BASE_ADDR, CRAB_ABORT_SIZE, "CRAB_ABORT" },
		{ 0, TPM_BASE_ADDRESS, TPM_SIZE, "TPM" },
		{ 0, LT_SECURITY_BASE_ADDR, LT_SECURITY_SIZE, "LT_SECURITY" },
		{ 0, IO_APIC_ADDR, APIC_SIZE, "APIC" },
		// PCH_PRESERVERD covers:
		// TraceHub SW BAR, SBREG, PMC MBAR, SPI BAR0, SerialIo BAR in ACPI mode
		// eSPI LGMR BAR, eSPI2 SEGMR BAR, TraceHub MTB BAR, TraceHub FW BAR
		// see fsp/ClientOneSiliconPkg/Fru/AdlPch/Include/PchReservedResourcesAdpP.h
		{ 0, PCH_PRESERVED_BASE_ADDRESS, PCH_PRESERVED_BASE_SIZE, "PCH_RESERVED" },
	};

	sa_add_fixed_mmio_resources(dev, index, soc_fixed_resources,
			ARRAY_SIZE(soc_fixed_resources));

	/* Add Vt-d resources if VT-d is enabled */
	if ((pci_read_config32(dev, CAPID0_A) & VTD_DISABLE))
		return;

	sa_add_fixed_mmio_resources(dev, index, soc_vtd_resources,
			ARRAY_SIZE(soc_vtd_resources));
}

/*
 * set MMIO resource's fields
 */
static void set_mmio_resource(
	struct sa_mmio_descriptor *resource,
	uint64_t base,
	uint64_t size,
	const char *description)
{
	if (resource == NULL) {
		printk(BIOS_ERR, "%s: argument resource is NULL for %s\n",
		__func__, description);
		return;
	}
	resource->base = base;
	resource->size = size;
	resource->description = description;
}

int soc_get_uncore_prmmr_base_and_mask(uint64_t *prmrr_base,
	uint64_t *prmrr_mask)
{
	msr_t msr;
	msr = rdmsr(MSR_PRMRR_BASE_0);
	*prmrr_base = (uint64_t)msr.hi << 32 | msr.lo;
	msr = rdmsr(MSR_PRMRR_PHYS_MASK);
	*prmrr_mask = (uint64_t)msr.hi << 32 | msr.lo;
	return 0;
}

/*
 * SoC implementation
 *
 * Add all known configurable memory ranges for Host Controller/Memory
 * controller.
 */
void soc_add_configurable_mmio_resources(struct device *dev, int *resource_cnt)
{
	uint64_t size, base, tseg_base;
	int count = 0;
	struct sa_mmio_descriptor cfg_rsrc[6]; /* Increase size when adding more resources */

	/* MMCONF */
	size = get_mmcfg_size(dev);
	if (size > 0)
		set_mmio_resource(&(cfg_rsrc[count++]), CONFIG_ECAM_MMCONF_BASE_ADDRESS,
			size, "MMCONF");

	/* DSM */
	size = get_dsm_size(dev);
	if (size > 0) {
		base = pci_read_config32(dev, BDSM) & 0xFFF00000;
		set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DSM");
	}

	/* TSEG */
	size = sa_get_tseg_size();
	tseg_base = sa_get_tseg_base();
	if (size > 0)
		set_mmio_resource(&(cfg_rsrc[count++]), tseg_base, size, "TSEG");

	/* PMRR */
	size = get_valid_prmrr_size();
	if (size > 0) {
		uint64_t mask;
		if (soc_get_uncore_prmmr_base_and_mask(&base, &mask) == 0) {
			base &= mask;
			set_mmio_resource(&(cfg_rsrc[count++]), base, size, "PMRR");
		} else {
			printk(BIOS_ERR, "SA: Failed to get PRMRR base and mask\n");
		}
	}

	/* GSM */
	size = get_gsm_size(dev);
	if (size > 0) {
		base = sa_get_gsm_base();
		set_mmio_resource(&(cfg_rsrc[count++]), base, size, "GSM");
	}

	/* DPR */
	size = get_dpr_size(dev);
	if (size > 0) {
		/* DPR just below TSEG: */
		base = tseg_base - size;
		set_mmio_resource(&(cfg_rsrc[count++]), base, size, "DPR");
	}

	/* Add all the above */
	sa_add_fixed_mmio_resources(dev, resource_cnt, cfg_rsrc, count);
}

/*
 * SoC implementation
 *
 * Perform System Agent Initialization during Ramstage phase.
 */
void soc_systemagent_init(struct device *dev)
{
	struct soc_power_limits_config *soc_config;
	struct device *sa;
	uint16_t sa_pci_id;
	u8 tdp;
	size_t i;
	config_t *config;

	/* Enable Power Aware Interrupt Routing */
	enable_power_aware_intr();

	config = config_of_soc();

	/* Get System Agent PCI ID */
	sa = pcidev_path_on_root(SA_DEVFN_ROOT);
	sa_pci_id = sa ? pci_read_config16(sa, PCI_DEVICE_ID) : 0xFFFF;

	tdp = get_cpu_tdp();

	/* Choose power limits configuration based on the CPU SA PCI ID and
	 * CPU TDP value. */
	for (i = 0; i < ARRAY_SIZE(cpuid_to_adl); i++) {
		if (sa_pci_id == cpuid_to_adl[i].cpu_id &&
				tdp == cpuid_to_adl[i].cpu_tdp) {
			soc_config = &config->power_limits_config[cpuid_to_adl[i].limits];
			set_power_limits(MOBILE_SKU_PL1_TIME_SEC, soc_config);
			break;
		}
	}

	if (i == ARRAY_SIZE(cpuid_to_adl)) {
		printk(BIOS_ERR, "unknown SA ID: 0x%4x, skipped power limits configuration.\n",
			sa_pci_id);
		return;
	}
}

uint32_t soc_systemagent_max_chan_capacity_mib(u8 capid0_a_ddrsz)
{
	switch (capid0_a_ddrsz) {
	case 1:
		return 8192;
	case 2:
		return 4096;
	case 3:
		return 2048;
	default:
		return 65536;
	}
}

uint64_t get_mmcfg_size(const struct device *dev)
{
	uint32_t pciexbar_reg;
	uint64_t mmcfg_length;

	if (!dev) {
		printk(BIOS_DEBUG, "%s : device is null\n", __func__);
		return 0;
	}

	pciexbar_reg = pci_read_config32(dev, PCIEXBAR);

	if (!(pciexbar_reg & (1 << 0))) {
		printk(BIOS_DEBUG, "%s : PCIEXBAR disabled\n", __func__);
		return 0;
	}

	switch ((pciexbar_reg & MASK_PCIEXBAR_LENGTH) >> PCIEXBAR_LENGTH_LSB) {
	case PCIEXBAR_LENGTH_4096MB:
		mmcfg_length = 4 * ((uint64_t)GiB);
		break;
	case PCIEXBAR_LENGTH_2048MB:
		mmcfg_length = 2 * ((uint64_t)GiB);
		break;
	case PCIEXBAR_LENGTH_1024MB:
		mmcfg_length = 1 * GiB;
		break;
	case PCIEXBAR_LENGTH_512MB:
		mmcfg_length = 512 * MiB;
		break;
	case PCIEXBAR_LENGTH_256MB:
		mmcfg_length = 256 * MiB;
		break;
	case PCIEXBAR_LENGTH_128MB:
		mmcfg_length = 128 * MiB;
		break;
	case PCIEXBAR_LENGTH_64MB:
		mmcfg_length = 64 * MiB;
		break;
	default:
		printk(BIOS_DEBUG, "%s : PCIEXBAR - invalid length (0x%x)\n", __func__,
			pciexbar_reg & MASK_PCIEXBAR_LENGTH);
		mmcfg_length = 0x0;
		break;
	}

	return mmcfg_length;
}

uint64_t get_dsm_size(const struct device *dev)
{
	// - size : B0/D0/F0:R 50h [15:8]
	uint32_t reg32 = pci_read_config32(dev, GGC);
	uint64_t size;
	uint32_t size_field = (reg32 & MASK_DSM_LENGTH) >> MASK_DSM_LENGTH_LSB;
	if (size_field <= 0x10) { // 0x0 - 0x10
		size = size_field * 32 * MiB;
	} else if ((size_field >= 0xF0) && (size_field >= 0xFE)) {
		size = ((uint64_t)size_field - 0xEF) * 4 * MiB;
	} else {
		switch (size_field) {
		case 0x20:
			size = 1 * GiB;
			break;
		case 0x30:
			size = 1536 * MiB;
			break;
		case 0x40:
			size = 2 * (uint64_t)GiB;
			break;
		default:
			printk(BIOS_DEBUG, "%s : DSM - invalid length (0x%x)\n",
				__func__, size_field);
			size = 0x0;
			break;
		}
	}
	return size;
}

uint64_t get_gsm_size(const struct device *dev)
{
	const u32 gsm_size = pci_read_config32(dev, GGC);
	uint64_t size;
	uint32_t size_field = (gsm_size & MASK_GSM_LENGTH) >> MASK_GSM_LENGTH_LSB;
	switch (size_field) {
	case 0x0:
		size = 0;
		break;
	case 0x1:
		size = 2 * MiB;
		break;
	case 0x2:
		size = 4 * MiB;
		break;
	case 0x3:
		size = 8 * MiB;
		break;
	default:
		size = 0;
		break;
	}
	return size;
}
uint64_t get_dpr_size(const struct device *dev)
{
	uint64_t size;
	uint32_t dpr_reg = pci_read_config32(dev, DPR);
	uint32_t size_field = (dpr_reg & MASK_DPR_LENGTH) >> MASK_DPR_LENGTH_LSB;
	size = (uint64_t)size_field * MiB;
	return size;
}
