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

#include <acpi/acpi_pm.h>
#include <arch/io.h>
#include <assert.h>
#include <bootmode.h>
#include <device/mmio.h>
#include <device/pci.h>
#include <cbmem.h>
#include <cpu/x86/smm.h>
#include <console/console.h>
#include <halt.h>
#include <intelblocks/pmc_ipc.h>
#include <intelblocks/pmclib.h>
#include <intelblocks/gpio.h>
#include <intelblocks/tco.h>
#include <option.h>
#include <security/vboot/vboot_common.h>
#include <soc/pci_devs.h>
#include <soc/pm.h>
#include <stdint.h>
#include <string.h>
#include <timer.h>

#define PMC_IPC_BIOS_RST_COMPLETE		0xd0
#define PMC_IPC_BIOS_RST_SUBID_PCI_ENUM_DONE	0

static struct chipset_power_state power_state;

/* List of Minimum Assertion durations in microseconds */
enum min_assert_dur {
	MinAssertDur0s		= 0,
	MinAssertDur60us	= 60,
	MinAssertDur1ms		= 1000,
	MinAssertDur50ms	= 50000,
	MinAssertDur98ms	= 98000,
	MinAssertDur500ms	= 500000,
	MinAssertDur1s		= 1000000,
	MinAssertDur2s		= 2000000,
	MinAssertDur3s		= 3000000,
	MinAssertDur4s		= 4000000,
};

/* Signal Assertion duration values */
struct cfg_assert_dur {
	/* Minimum assertion duration of SLP_A signal */
	enum min_assert_dur slp_a;

	/* Minimum assertion duration of SLP_4 signal */
	enum min_assert_dur slp_s4;

	/* Minimum assertion duration of SLP_3 signal */
	enum min_assert_dur slp_s3;

	/* PCH PM Power Cycle duration */
	enum min_assert_dur pm_pwr_cyc_dur;
};

/* Default value of PchPmPwrCycDur */
#define PCH_PM_PWR_CYC_DUR	0

struct chipset_power_state *pmc_get_power_state(void)
{
	struct chipset_power_state *ptr = NULL;

	if (cbmem_possibly_online())
		ptr = acpi_get_pm_state();

	/* cbmem is online but ptr is not populated yet */
	if (ptr == NULL && !(ENV_RAMSTAGE || ENV_POSTCAR))
		return &power_state;

	return ptr;
}

static void migrate_power_state(int is_recovery)
{
	struct chipset_power_state *ps_cbmem;

	ps_cbmem = cbmem_add(CBMEM_ID_POWER_STATE, sizeof(*ps_cbmem));

	if (ps_cbmem == NULL) {
		printk(BIOS_DEBUG, "Not adding power state to cbmem!\n");
		return;
	}
	memcpy(ps_cbmem, &power_state, sizeof(*ps_cbmem));
}
CBMEM_CREATION_HOOK(migrate_power_state);

static void print_num_status_bits(int num_bits, uint32_t status,
				  const char *const bit_names[])
{
	int i;

	if (!status)
		return;

	for (i = num_bits - 1; i >= 0; i--) {
		if (status & (1 << i)) {
			if (bit_names[i])
				printk(BIOS_DEBUG, "%s ", bit_names[i]);
			else
				printk(BIOS_DEBUG, "BIT%d ", i);
		}
	}
}

__weak uint32_t soc_get_smi_status(uint32_t generic_sts)
{
	return generic_sts;
}

int acpi_get_sleep_type(void)
{
	struct chipset_power_state *ps;
	int prev_sleep_state = ACPI_S0;

	ps = pmc_get_power_state();
	if (ps)
		prev_sleep_state = ps->prev_sleep_state;

	return prev_sleep_state;
}

static uint32_t pmc_reset_smi_status(void)
{
	uint32_t smi_sts = inl(ACPI_BASE_ADDRESS + SMI_STS);
	outl(smi_sts, ACPI_BASE_ADDRESS + SMI_STS);

	return soc_get_smi_status(smi_sts);
}

static uint32_t print_smi_status(uint32_t smi_sts)
{
	size_t array_size;
	const char *const *smi_arr;

	if (!smi_sts)
		return 0;

	printk(BIOS_DEBUG, "SMI_STS: ");

	smi_arr = soc_smi_sts_array(&array_size);

	print_num_status_bits(array_size, smi_sts, smi_arr);
	printk(BIOS_DEBUG, "\n");

	return smi_sts;
}

/*
 * Update supplied events in PM1_EN register. This does not disable any already
 * set events.
 */
void pmc_update_pm1_enable(u16 events)
{
	u16 pm1_en = pmc_read_pm1_enable();
	pm1_en |= events;
	pmc_enable_pm1(pm1_en);
}

/* Read events set in PM1_EN register. */
uint16_t pmc_read_pm1_enable(void)
{
	return inw(ACPI_BASE_ADDRESS + PM1_EN);
}

uint32_t pmc_clear_smi_status(void)
{
	uint32_t sts = pmc_reset_smi_status();

	return print_smi_status(sts);
}

uint32_t pmc_get_smi_en(void)
{
	return inl(ACPI_BASE_ADDRESS + SMI_EN);
}

void pmc_enable_smi(uint32_t mask)
{
	uint32_t smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
	smi_en |= mask;
	outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
}

void pmc_disable_smi(uint32_t mask)
{
	uint32_t smi_en = inl(ACPI_BASE_ADDRESS + SMI_EN);
	smi_en &= ~mask;
	outl(smi_en, ACPI_BASE_ADDRESS + SMI_EN);
}

/* PM1 */
void pmc_enable_pm1(uint16_t events)
{
	outw(events, ACPI_BASE_ADDRESS + PM1_EN);
}

uint32_t pmc_read_pm1_control(void)
{
	return inl(ACPI_BASE_ADDRESS + PM1_CNT);
}

void pmc_write_pm1_control(uint32_t pm1_cnt)
{
	outl(pm1_cnt, ACPI_BASE_ADDRESS + PM1_CNT);
}

void pmc_enable_pm1_control(uint32_t mask)
{
	uint32_t pm1_cnt = pmc_read_pm1_control();
	pm1_cnt |= mask;
	pmc_write_pm1_control(pm1_cnt);
}

void pmc_disable_pm1_control(uint32_t mask)
{
	uint32_t pm1_cnt = pmc_read_pm1_control();
	pm1_cnt &= ~mask;
	pmc_write_pm1_control(pm1_cnt);
}

static uint16_t reset_pm1_status(void)
{
	uint16_t pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
	outw(pm1_sts, ACPI_BASE_ADDRESS + PM1_STS);
	return pm1_sts;
}

static uint16_t print_pm1_status(uint16_t pm1_sts)
{
	static const char *const pm1_sts_bits[] = {
		[0] = "TMROF",
		[5] = "GBL",
		[8] = "PWRBTN",
		[10] = "RTC",
		[11] = "PRBTNOR",
		[13] = "USB",
		[14] = "PCIEXPWAK",
		[15] = "WAK",
	};

	if (!pm1_sts)
		return 0;

	printk(BIOS_DEBUG, "PM1_STS: ");
	print_num_status_bits(ARRAY_SIZE(pm1_sts_bits), pm1_sts, pm1_sts_bits);
	printk(BIOS_DEBUG, "\n");

	return pm1_sts;
}

uint16_t pmc_clear_pm1_status(void)
{
	return print_pm1_status(reset_pm1_status());
}

/* TCO */

static uint32_t print_tco_status(uint32_t tco_sts)
{
	size_t array_size;
	const char *const *tco_arr;

	if (!tco_sts)
		return 0;

	printk(BIOS_DEBUG, "TCO_STS: ");

	tco_arr = soc_tco_sts_array(&array_size);

	print_num_status_bits(array_size, tco_sts, tco_arr);
	printk(BIOS_DEBUG, "\n");

	return tco_sts;
}

uint32_t pmc_clear_tco_status(void)
{
	return print_tco_status(tco_reset_status());
}

/* GPE */
static void pmc_enable_gpe(int gpe, uint32_t mask)
{
	uint32_t gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(gpe));
	gpe0_en |= mask;
	outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(gpe));
}

static void pmc_disable_gpe(int gpe, uint32_t mask)
{
	uint32_t gpe0_en = inl(ACPI_BASE_ADDRESS + GPE0_EN(gpe));
	gpe0_en &= ~mask;
	outl(gpe0_en, ACPI_BASE_ADDRESS + GPE0_EN(gpe));
}

void pmc_enable_std_gpe(uint32_t mask)
{
	pmc_enable_gpe(GPE_STD, mask);
}

void pmc_disable_std_gpe(uint32_t mask)
{
	pmc_disable_gpe(GPE_STD, mask);
}

void pmc_disable_all_gpe(void)
{
	int i;
	for (i = 0; i < GPE0_REG_MAX; i++)
		pmc_disable_gpe(i, ~0);
}

/* Clear the gpio gpe0 status bits in ACPI registers */
static void pmc_clear_gpi_gpe_status(void)
{
	int i;

	for (i = 0; i < GPE0_REG_MAX; i++) {
		/* This is reserved GPE block and specific to chipset */
		if (i == GPE_STD)
			continue;
		uint32_t gpe_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS(i));
		outl(gpe_sts, ACPI_BASE_ADDRESS + GPE0_STS(i));
	}
}

static uint32_t reset_std_gpe_status(void)
{
	uint32_t gpe_sts = inl(ACPI_BASE_ADDRESS + GPE0_STS(GPE_STD));
	outl(gpe_sts, ACPI_BASE_ADDRESS + GPE0_STS(GPE_STD));
	return gpe_sts;
}

static uint32_t print_std_gpe_sts(uint32_t gpe_sts)
{
	size_t array_size;
	const char *const *sts_arr;

	if (!gpe_sts)
		return gpe_sts;

	printk(BIOS_DEBUG, "GPE0 STD STS: ");

	sts_arr = soc_std_gpe_sts_array(&array_size);
	print_num_status_bits(array_size, gpe_sts, sts_arr);
	printk(BIOS_DEBUG, "\n");

	return gpe_sts;
}

static void pmc_clear_std_gpe_status(void)
{
	print_std_gpe_sts(reset_std_gpe_status());
}

void pmc_clear_all_gpe_status(void)
{
	pmc_clear_std_gpe_status();
	pmc_clear_gpi_gpe_status();
}

__weak
void soc_clear_pm_registers(uintptr_t pmc_bar)
{
}

void pmc_or_mmio32(uint32_t offset, uint32_t ormask)
{
	uint32_t reg;
	uintptr_t pmc_bar;

	pmc_bar = soc_read_pmc_base();
	reg = read32p(pmc_bar + offset);
	reg |= ormask;
	write32p(pmc_bar + offset, reg);
}

void pmc_clear_prsts(void)
{
	uint32_t prsts;
	uintptr_t pmc_bar;

	/* Read PMC base address from soc */
	pmc_bar = soc_read_pmc_base();

	prsts = read32p(pmc_bar + PRSTS);
	write32p(pmc_bar + PRSTS, prsts);

	soc_clear_pm_registers(pmc_bar);
}

__weak
int soc_prev_sleep_state(const struct chipset_power_state *ps,
			      int prev_sleep_state)
{
	return prev_sleep_state;
}

/*
 * Returns prev_sleep_state and also prints all power management registers.
 * Calls soc_prev_sleep_state which may be implemented by SOC.
 */
static int pmc_prev_sleep_state(const struct chipset_power_state *ps)
{
	/* Default to S0. */
	int prev_sleep_state = ACPI_S0;

	if (ps->pm1_sts & WAK_STS) {
		switch (acpi_sleep_from_pm1(ps->pm1_cnt)) {
		case ACPI_S3:
			if (CONFIG(HAVE_ACPI_RESUME))
				prev_sleep_state = ACPI_S3;
			break;
		case ACPI_S4:
			prev_sleep_state = ACPI_S4;
			break;
		case ACPI_S5:
			prev_sleep_state = ACPI_S5;
			break;
		}

		/* Clear SLP_TYP. */
		pmc_write_pm1_control(ps->pm1_cnt & ~(SLP_TYP));
	}

	prev_sleep_state = soc_prev_sleep_state(ps, prev_sleep_state);

	/* Clear PMC PMCON_x register power failure status bits. */
	pmc_clear_pmcon_pwr_failure_sts();

	return prev_sleep_state;
}

void pmc_fill_pm_reg_info(struct chipset_power_state *ps)
{
	int i;

	memset(ps, 0, sizeof(*ps));

	ps->pm1_sts = inw(ACPI_BASE_ADDRESS + PM1_STS);
	ps->pm1_en = inw(ACPI_BASE_ADDRESS + PM1_EN);
	ps->pm1_cnt = pmc_read_pm1_control();

	printk(BIOS_DEBUG, "pm1_sts: %04x pm1_en: %04x pm1_cnt: %08x\n",
	       ps->pm1_sts, ps->pm1_en, ps->pm1_cnt);

	for (i = 0; i < GPE0_REG_MAX; i++) {
		ps->gpe0_sts[i] = inl(ACPI_BASE_ADDRESS + GPE0_STS(i));
		ps->gpe0_en[i] = inl(ACPI_BASE_ADDRESS + GPE0_EN(i));
		printk(BIOS_DEBUG, "gpe0_sts[%d]: %08x gpe0_en[%d]: %08x\n",
		       i, ps->gpe0_sts[i], i, ps->gpe0_en[i]);
	}

	soc_fill_power_state(ps);
}

/* Reads and prints ACPI specific PM registers */
int pmc_fill_power_state(struct chipset_power_state *ps)
{
	pmc_fill_pm_reg_info(ps);

	ps->prev_sleep_state = pmc_prev_sleep_state(ps);
	printk(BIOS_DEBUG, "prev_sleep_state %d\n", ps->prev_sleep_state);

	return ps->prev_sleep_state;
}

#if CONFIG(PMC_GLOBAL_RESET_ENABLE_LOCK)
void pmc_global_reset_disable_and_lock(void)
{
	uint32_t *etr = soc_pmc_etr_addr();
	uint32_t reg;

	reg = read32(etr);
	reg = (reg & ~CF9_GLB_RST) | CF9_LOCK;
	write32(etr, reg);
}

void pmc_global_reset_enable(bool enable)
{
	uint32_t *etr = soc_pmc_etr_addr();
	uint32_t reg;

	reg = read32(etr);
	reg = enable ? reg | CF9_GLB_RST : reg & ~CF9_GLB_RST;
	write32(etr, reg);
}
#endif // CONFIG_PMC_GLOBAL_RESET_ENABLE_LOCK

int platform_is_resuming(void)
{
	/* Read power state from PMC data structure */
	if (ENV_RAMSTAGE)
		return acpi_get_sleep_type() == ACPI_S3;

	/* Read power state from PMC ABASE */
	if (!(inw(ACPI_BASE_ADDRESS + PM1_STS) & WAK_STS))
		return 0;

	return acpi_sleep_from_pm1(pmc_read_pm1_control()) == ACPI_S3;
}

/* Read and clear GPE status (defined in acpi/acpi.h) */
int acpi_get_gpe(int gpe)
{
	int bank;
	uint32_t mask, sts;
	struct stopwatch sw;
	int rc = 0;

	if (gpe < 0 || gpe > GPE_MAX)
		return -1;

	bank = gpe / 32;
	mask = 1 << (gpe % 32);

	/* Wait up to 1ms for GPE status to clear */
	stopwatch_init_msecs_expire(&sw, 1);
	do {
		if (stopwatch_expired(&sw))
			return rc;

		sts = inl(ACPI_BASE_ADDRESS + GPE0_STS(bank));
		if (sts & mask) {
			outl(mask, ACPI_BASE_ADDRESS + GPE0_STS(bank));
			rc = 1;
		}
	} while (sts & mask);

	return rc;
}

/*
 * The PM1 control is set to S5 when vboot requests a reboot because the power
 * state code above may not have collected its data yet. Therefore, set it to
 * S5 when vboot requests a reboot. That's necessary if vboot fails in the
 * resume path and requests a reboot. This prevents a reboot loop where the
 * error is continually hit on the failing vboot resume path.
 */
void vboot_platform_prepare_reboot(void)
{
	uint32_t pm1_cnt;
	pm1_cnt = (pmc_read_pm1_control() & ~(SLP_TYP)) |
		(SLP_TYP_S5 << SLP_TYP_SHIFT);
	pmc_write_pm1_control(pm1_cnt);
}

void poweroff(void)
{
	pmc_enable_pm1_control(SLP_EN | (SLP_TYP_S5 << SLP_TYP_SHIFT));

	/*
	 * Setting SLP_TYP_S5 in PM1 triggers SLP_SMI, which is handled by SMM
	 * to transition to S5 state. If halt is called in SMM, then it prevents
	 * the SMI handler from being triggered and system never enters S5.
	 */
	if (!ENV_SMM)
		halt();
}

void pmc_gpe_init(void)
{
	uint32_t gpio_cfg = 0;
	uint32_t gpio_cfg_reg;
	uint8_t dw0, dw1, dw2;

	/* Read PMC base address from soc. This is implemented in soc */
	uintptr_t pmc_bar = soc_read_pmc_base();

	/*
	 * Get the dwX values for pmc gpe settings.
	 */
	soc_get_gpi_gpe_configs(&dw0, &dw1, &dw2);

	const uint32_t gpio_cfg_mask =
	    (GPE0_DWX_MASK << GPE0_DW_SHIFT(0)) |
	    (GPE0_DWX_MASK << GPE0_DW_SHIFT(1)) |
	    (GPE0_DWX_MASK << GPE0_DW_SHIFT(2));

	/* Making sure that bad values don't bleed into the other fields */
	dw0 &= GPE0_DWX_MASK;
	dw1 &= GPE0_DWX_MASK;
	dw2 &= GPE0_DWX_MASK;

	/*
	 * Route the GPIOs to the GPE0 block. Determine that all values
	 * are different, and if they aren't use the reset values.
	 */
	if (dw0 == dw1 || dw1 == dw2) {
		printk(BIOS_INFO, "PMC: Using default GPE route.\n");
		gpio_cfg = read32p(pmc_bar + GPIO_GPE_CFG);

		dw0 = (gpio_cfg >> GPE0_DW_SHIFT(0)) & GPE0_DWX_MASK;
		dw1 = (gpio_cfg >> GPE0_DW_SHIFT(1)) & GPE0_DWX_MASK;
		dw2 = (gpio_cfg >> GPE0_DW_SHIFT(2)) & GPE0_DWX_MASK;
	} else {
		gpio_cfg |= (uint32_t)dw0 << GPE0_DW_SHIFT(0);
		gpio_cfg |= (uint32_t)dw1 << GPE0_DW_SHIFT(1);
		gpio_cfg |= (uint32_t)dw2 << GPE0_DW_SHIFT(2);
	}

	gpio_cfg_reg = read32p(pmc_bar + GPIO_GPE_CFG) & ~gpio_cfg_mask;
	gpio_cfg_reg |= gpio_cfg & gpio_cfg_mask;

	write32p(pmc_bar + GPIO_GPE_CFG, gpio_cfg_reg);

	/* Set the routes in the GPIO communities as well. */
	gpio_route_gpe(dw0, dw1, dw2);
}

static void pmc_clear_pmcon_pwr_failure_sts_mmio(void)
{
	uint8_t *addr = pmc_mmio_regs();

	/*
	 * Clear PMC GEN_PMCON_A register power failure status bits:
	 * SUS_PWR_FLR, PWR_FLR bits
	 * while retaining MS4V write-1-to-clear bit
	 *
	 * Note: clearing `GBL_RST_STS` bit earlier than FSP-M/MRC having an adverse effect
	 * on the PMC sleep type register which results in calculating wrong
	 * `prev_sleep_state` post a global reset, hence, just clearing the power failure
	 * status bits rather than clearing the complete PMC PMCON_A register.
	 */
	clrbits32((addr + GEN_PMCON_A), (MS4V | GBL_RST_STS));
}

static void pmc_clear_pmcon_pwr_failure_sts_pci(void)
{
#if defined(__SIMPLE_DEVICE__)
	pci_devfn_t dev = PCI_DEV(0, PCI_SLOT(PCH_DEVFN_PMC), PCI_FUNC(PCH_DEVFN_PMC));
#else
	struct device *dev = pcidev_path_on_root(PCH_DEVFN_PMC);
	if (!dev)
		return;
#endif

	pci_or_config32(dev, GEN_PMCON_B, (SUS_PWR_FLR | PWR_FLR));
}

/*
 * Clear PMC GEN_PMCON_X register power failure status bits:
 * SUS_PWR_FLR, PWR_FLR bits (keep the other bits intact)
 */
void pmc_clear_pmcon_pwr_failure_sts(void)
{
	if (CONFIG(SOC_INTEL_MEM_MAPPED_PM_CONFIGURATION))
		pmc_clear_pmcon_pwr_failure_sts_mmio();
	else
		pmc_clear_pmcon_pwr_failure_sts_pci();
}

#if ENV_RAMSTAGE
static void pmc_clear_pmcon_sts_mmio(void)
{
	uint8_t *addr = pmc_mmio_regs();

	clrbits32((addr + GEN_PMCON_A), MS4V);
}

static void pmc_clear_pmcon_sts_pci(void)
{
	struct device *dev = pcidev_path_on_root(PCH_DEVFN_PMC);
	if (!dev)
		return;

	pci_and_config32(dev, GEN_PMCON_A, ~MS4V);
}

/*
 * Clear PMC GEN_PMCON_A register status bits:
 * SUS_PWR_FLR, GBL_RST_STS, HOST_RST_STS, PWR_FLR bits
 * while retaining MS4V write-1-to-clear bit
 */
void pmc_clear_pmcon_sts(void)
{
	/*
	 * Accessing PMC GEN_PMCON_A register differs between different Intel chipsets.
	 * Typically, there are two possible ways to perform GEN_PMCON_A register programming
	 * (like `pmc_clear_pmcon_sts()`) as:
	 * 1. Using PCI configuration space when GEN_PMCON_A is a PCI configuration register.
	 * 2. Using MMIO access when GEN_PMCON_A is a memory mapped register.
	 */
	if (CONFIG(SOC_INTEL_MEM_MAPPED_PM_CONFIGURATION))
		pmc_clear_pmcon_sts_mmio();
	else
		pmc_clear_pmcon_sts_pci();
}
#endif

void pmc_set_power_failure_state(const bool target_on)
{
	const unsigned int state = get_uint_option("power_on_after_fail",
					 CONFIG_MAINBOARD_POWER_FAILURE_STATE);

	/*
	 * On the shutdown path (target_on == false), we only need to
	 * update the register for MAINBOARD_POWER_STATE_PREVIOUS. For
	 * all other cases, we don't write the register to avoid clob-
	 * bering the value set on the boot path. This is necessary,
	 * for instance, when we can't access the option backend in SMM.
	 */

	switch (state) {
	case MAINBOARD_POWER_STATE_OFF:
		if (!target_on)
			break;
		printk(BIOS_INFO, "Set power off after power failure.\n");
		pmc_soc_set_afterg3_en(false);
		break;
	case MAINBOARD_POWER_STATE_ON:
		if (!target_on)
			break;
		printk(BIOS_INFO, "Set power on after power failure.\n");
		pmc_soc_set_afterg3_en(true);
		break;
	case MAINBOARD_POWER_STATE_PREVIOUS:
		printk(BIOS_INFO, "Keep power state after power failure.\n");
		pmc_soc_set_afterg3_en(target_on);
		break;
	default:
		printk(BIOS_WARNING, "Unknown power-failure state: %d\n", state);
		break;
	}
}

/* This function returns the highest assertion duration of the SLP_Sx assertion widths */
static enum min_assert_dur get_high_assert_width(const struct cfg_assert_dur *cfg_assert_dur)
{
	enum min_assert_dur max_assert_dur = cfg_assert_dur->slp_s4;

	if (max_assert_dur < cfg_assert_dur->slp_s3)
		max_assert_dur = cfg_assert_dur->slp_s3;

	if (max_assert_dur < cfg_assert_dur->slp_a)
		max_assert_dur = cfg_assert_dur->slp_a;

	return max_assert_dur;
}

/* This function converts assertion durations from register-encoded to microseconds */
static void get_min_assert_dur(uint8_t slp_s4_min_assert, uint8_t slp_s3_min_assert,
		uint8_t slp_a_min_assert, uint8_t pm_pwr_cyc_dur,
		struct cfg_assert_dur *cfg_assert_dur)
{
	/*
	 * Ensure slp_x_dur_list[] elements in the devicetree config are in sync with
	 * FSP encoded values.
	 */

	/* slp_s4_assert_dur_list : 1s, 1s(default), 2s, 3s, 4s */
	const enum min_assert_dur slp_s4_assert_dur_list[] = {
		MinAssertDur1s, MinAssertDur1s, MinAssertDur2s, MinAssertDur3s, MinAssertDur4s
	};

	/* slp_s3_assert_dur_list: 50ms, 60us, 1ms, 50ms (Default), 2s */
	const enum min_assert_dur slp_s3_assert_dur_list[] = {
		MinAssertDur50ms, MinAssertDur60us, MinAssertDur1ms, MinAssertDur50ms,
										MinAssertDur2s
	};

	/* slp_a_assert_dur_list: 2s, 0s, 4s, 98ms, 2s(Default) */
	const enum min_assert_dur slp_a_assert_dur_list[] = {
		MinAssertDur2s, MinAssertDur0s, MinAssertDur4s, MinAssertDur98ms, MinAssertDur2s
	};

	/* pm_pwr_cyc_dur_list: 4s(Default), 1s, 2s, 3s, 4s */
	const enum min_assert_dur pm_pwr_cyc_dur_list[] = {
		MinAssertDur4s, MinAssertDur1s, MinAssertDur2s, MinAssertDur3s, MinAssertDur4s
	};

	/* Get signal assertion width */
	if (slp_s4_min_assert < ARRAY_SIZE(slp_s4_assert_dur_list))
		cfg_assert_dur->slp_s4 = slp_s4_assert_dur_list[slp_s4_min_assert];

	if (slp_s3_min_assert < ARRAY_SIZE(slp_s3_assert_dur_list))
		cfg_assert_dur->slp_s3 = slp_s3_assert_dur_list[slp_s3_min_assert];

	if (slp_a_min_assert < ARRAY_SIZE(slp_a_assert_dur_list))
		cfg_assert_dur->slp_a = slp_a_assert_dur_list[slp_a_min_assert];

	if (pm_pwr_cyc_dur < ARRAY_SIZE(pm_pwr_cyc_dur_list))
		cfg_assert_dur->pm_pwr_cyc_dur = pm_pwr_cyc_dur_list[pm_pwr_cyc_dur];
}

/*
 * This function ensures that the duration programmed in the PchPmPwrCycDur will never be
 * smaller than the SLP_Sx assertion widths.
 * If the pm_pwr_cyc_dur is less than any of the SLP_Sx assertion widths then it returns the
 * default value PCH_PM_PWR_CYC_DUR.
 */
uint8_t get_pm_pwr_cyc_dur(uint8_t slp_s4_min_assert, uint8_t slp_s3_min_assert,
		uint8_t slp_a_min_assert, uint8_t pm_pwr_cyc_dur)
{
	/* Set default values for the minimum assertion duration */
	struct cfg_assert_dur cfg_assert_dur = {
		.slp_a		= MinAssertDur2s,
		.slp_s4		= MinAssertDur1s,
		.slp_s3		= MinAssertDur50ms,
		.pm_pwr_cyc_dur	= MinAssertDur4s
	};

	enum min_assert_dur high_assert_width;

	/* Convert assertion durations from register-encoded to microseconds */
	get_min_assert_dur(slp_s4_min_assert, slp_s3_min_assert, slp_a_min_assert,
		pm_pwr_cyc_dur,	&cfg_assert_dur);

	/* Get the highest assertion duration among PCH EDS specified signals for pwr_cyc_dur */
	high_assert_width = get_high_assert_width(&cfg_assert_dur);

	if (cfg_assert_dur.pm_pwr_cyc_dur >= high_assert_width)
		return pm_pwr_cyc_dur;

	printk(BIOS_DEBUG,
			"Set PmPwrCycDur to 4s as configured PmPwrCycDur (%d) violates PCH EDS "
			"spec\n", pm_pwr_cyc_dur);

	return PCH_PM_PWR_CYC_DUR;
}

void pmc_set_acpi_mode(void)
{
	if (!CONFIG(NO_SMM) && !acpi_is_wakeup_s3()) {
		apm_control(APM_CNT_ACPI_DISABLE);
	}
}

enum pch_pmc_xtal pmc_get_xtal_freq(void)
{
	if (!CONFIG(SOC_INTEL_COMMON_BLOCK_PMC_EPOC))
		dead_code();

	uint32_t xtal_freq = 0;
	const uint32_t epoc = read32p(soc_read_pmc_base() + PCH_PMC_EPOC);

	/* XTAL frequency in bits 21, 20, 17 */
	xtal_freq |= !!(epoc & (1 << 21)) << 2;
	xtal_freq |= !!(epoc & (1 << 20)) << 1;
	xtal_freq |= !!(epoc & (1 << 17)) << 0;
	switch (xtal_freq) {
	case 0:
		return XTAL_24_MHZ;
	case 1:
		return XTAL_19_2_MHZ;
	case 2:
		return XTAL_38_4_MHZ;
	default:
		printk(BIOS_ERR, "Unknown EPOC XTAL frequency setting %u\n", xtal_freq);
		return XTAL_UNKNOWN_FREQ;
	}
}

void pmc_send_pci_enum_done(void)
{
	struct pmc_ipc_buffer req = { 0 };
	struct pmc_ipc_buffer rsp;
	uint32_t cmd;

	cmd = pmc_make_ipc_cmd(PMC_IPC_BIOS_RST_COMPLETE,
			 PMC_IPC_BIOS_RST_SUBID_PCI_ENUM_DONE, 0);
	if (pmc_send_ipc_cmd(cmd, &req, &rsp) != CB_SUCCESS)
		printk(BIOS_ERR, "PMC: Failed sending PCI Enumeration Done Command\n");
}
