From 2eb37453e56f3c0dc2dd7c1f23c26af080cdac7c Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Thu, 26 Feb 2026 10:01:36 -0800 Subject: [PATCH] soc/intel/meteorlake: Use common pmutil driver Migrate Meteor Lake to use the common PMC utility driver instead of maintaining platform-specific pmutil.c code. This change: - Enables SOC_INTEL_COMMON_FEATURE_PMUTIL in Kconfig - Removes platform-specific pmutil.c - Removes pmutil.c from Makefile.mk The common driver provides all necessary functionality through the generic config_t interface, eliminating ~290 lines of duplicated code. Change-Id: I1c46a517420c8ea7410c4ed7e8e7b761d4399cf9 Signed-off-by: Jeremy Compostella Reviewed-on: https://review.coreboot.org/c/coreboot/+/91240 Tested-by: build bot (Jenkins) Reviewed-by: Huang, Cliff --- src/soc/intel/meteorlake/Kconfig | 1 + src/soc/intel/meteorlake/Makefile.mk | 2 - src/soc/intel/meteorlake/include/soc/pm.h | 3 - src/soc/intel/meteorlake/ioe_pmc.c | 5 + src/soc/intel/meteorlake/pmutil.c | 286 ---------------------- 5 files changed, 6 insertions(+), 291 deletions(-) delete mode 100644 src/soc/intel/meteorlake/pmutil.c diff --git a/src/soc/intel/meteorlake/Kconfig b/src/soc/intel/meteorlake/Kconfig index 6ec4c9aaa7..1ec20d25de 100644 --- a/src/soc/intel/meteorlake/Kconfig +++ b/src/soc/intel/meteorlake/Kconfig @@ -89,6 +89,7 @@ config SOC_INTEL_METEORLAKE select SOC_INTEL_COMMON_FEATURE select SOC_INTEL_COMMON_FEATURE_ESPI select SOC_INTEL_COMMON_FEATURE_GSPI_DEVFN + select SOC_INTEL_COMMON_FEATURE_PMUTIL select SOC_INTEL_COMMON_FEATURE_SOUNDWIRE select SOC_INTEL_COMMON_FEATURE_SPI_DEVFN select SOC_INTEL_COMMON_FEATURE_SPI_DEVFN_PSF diff --git a/src/soc/intel/meteorlake/Makefile.mk b/src/soc/intel/meteorlake/Makefile.mk index a6c77a8bdd..19ffa96d0e 100644 --- a/src/soc/intel/meteorlake/Makefile.mk +++ b/src/soc/intel/meteorlake/Makefile.mk @@ -6,7 +6,6 @@ subdirs-y += ../../../cpu/intel/microcode subdirs-y += ../../../cpu/intel/turbo # all (bootblock, verstage, romstage, postcar, ramstage) -all-y += pmutil.c all-y += gpio.c bootblock-y += bootblock/bootblock.c @@ -44,7 +43,6 @@ ramstage-y += soc_info.c smm-y += elog.c smm-y += gpio.c smm-y += p2sb.c -smm-y += pmutil.c smm-y += smihandler.c smm-y += soc_info.c smm-y += xhci.c diff --git a/src/soc/intel/meteorlake/include/soc/pm.h b/src/soc/intel/meteorlake/include/soc/pm.h index 7474cdd8bc..c486232e7d 100644 --- a/src/soc/intel/meteorlake/include/soc/pm.h +++ b/src/soc/intel/meteorlake/include/soc/pm.h @@ -150,9 +150,6 @@ struct chipset_power_state { /* Get base address PMC memory mapped registers. */ uint8_t *pmc_mmio_regs(void); -/* Get base address IOE.PMC memory mapped registers. */ -uint8_t *ioe_pmc_mmio_regs(void); - /* Get base address of TCO I/O registers. */ uint16_t smbus_tco_regs(void); diff --git a/src/soc/intel/meteorlake/ioe_pmc.c b/src/soc/intel/meteorlake/ioe_pmc.c index 418c4a5535..e2fb49be4d 100644 --- a/src/soc/intel/meteorlake/ioe_pmc.c +++ b/src/soc/intel/meteorlake/ioe_pmc.c @@ -5,6 +5,11 @@ #include #include +static uint8_t *ioe_pmc_mmio_regs(void) +{ + return (void *)(uintptr_t)IOE_PWRM_BASE_ADDRESS; +} + static void ioe_pmc_read_resources(struct device *dev) { /* Add the fixed MMIO resource */ diff --git a/src/soc/intel/meteorlake/pmutil.c b/src/soc/intel/meteorlake/pmutil.c deleted file mode 100644 index a0bba92f11..0000000000 --- a/src/soc/intel/meteorlake/pmutil.c +++ /dev/null @@ -1,286 +0,0 @@ -/* SPDX-License-Identifier: GPL-2.0-only */ - -/* - * Helper functions for dealing with power management registers - * and the differences between PCH variants. - */ - -#define __SIMPLE_DEVICE__ - -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -/* - * SMI - */ -const char *const *soc_smi_sts_array(size_t *a) -{ - static const char *const smi_sts_bits[] = { - [BIOS_STS_BIT] = "BIOS", - [LEGACY_USB_STS_BIT] = "LEGACY_USB", - [SMI_ON_SLP_EN_STS_BIT] = "SLP_SMI", - [APM_STS_BIT] = "APM", - [SWSMI_TMR_STS_BIT] = "SWSMI_TMR", - [PM1_STS_BIT] = "PM1", - [GPE0_STS_BIT] = "GPE0", - [GPIO_STS_BIT] = "GPI", - [MCSMI_STS_BIT] = "MCSMI", - [DEVMON_STS_BIT] = "DEVMON", - [TCO_STS_BIT] = "TCO", - [PERIODIC_STS_BIT] = "PERIODIC", - [SERIRQ_SMI_STS_BIT] = "SERIRQ_SMI", - [SMBUS_SMI_STS_BIT] = "SMBUS_SMI", - [PCI_EXP_SMI_STS_BIT] = "PCI_EXP_SMI", - [MONITOR_STS_BIT] = "MONITOR", - [SPI_SMI_STS_BIT] = "SPI", - [GPIO_UNLOCK_SMI_STS_BIT] = "GPIO_UNLOCK", - [ESPI_SMI_STS_BIT] = "ESPI_SMI", - }; - - *a = ARRAY_SIZE(smi_sts_bits); - return smi_sts_bits; -} - -/* - * TCO - */ -const char *const *soc_tco_sts_array(size_t *a) -{ - static const char *const tco_sts_bits[] = { - [0] = "NMI2SMI", - [1] = "SW_TCO", - [2] = "TCO_INT", - [3] = "TIMEOUT", - [7] = "NEWCENTURY", - [8] = "BIOSWR", - [9] = "DMISCI", - [10] = "DMISMI", - [12] = "DMISERR", - [13] = "SLVSEL", - [16] = "INTRD_DET", - [17] = "SECOND_TO", - [18] = "BOOT", - [20] = "SMLINK_SLV" - }; - - *a = ARRAY_SIZE(tco_sts_bits); - return tco_sts_bits; -} - -/* - * GPE0 - */ -const char *const *soc_std_gpe_sts_array(size_t *a) -{ - static const char *const gpe_sts_bits[] = { - [1] = "HOTPLUG", - [2] = "SWGPE", - [6] = "TCO_SCI", - [7] = "SMB_WAK", - [9] = "PCI_EXP", - [10] = "BATLOW", - [11] = "PME", - [12] = "ME", - [13] = "PME_B0", - [14] = "eSPI", - [15] = "GPIO Tier-2", - [16] = "LAN_WAKE", - [18] = "WADT" - }; - - *a = ARRAY_SIZE(gpe_sts_bits); - return gpe_sts_bits; -} - -void pmc_set_disb(void) -{ - /* Set the DISB after DRAM init */ - uint8_t disb_val; - /* Only care about bits [23:16] of register GEN_PMCON_A */ - uint8_t *addr = (uint8_t *)(pmc_mmio_regs() + GEN_PMCON_A + 2); - - disb_val = read8(addr); - disb_val |= (DISB >> 16); - - /* Don't clear bits that are write-1-to-clear */ - disb_val &= ~((MS4V | SUS_PWR_FLR) >> 16); - write8(addr, disb_val); -} - -/* - * PMC controller gets hidden from PCI bus - * during FSP-Silicon init call. Hence PWRMBASE - * can't be accessible using PCI configuration space - * read/write. - */ -uint8_t *pmc_mmio_regs(void) -{ - return (void *)(uintptr_t)PCH_PWRM_BASE_ADDRESS; -} - -uint8_t *ioe_pmc_mmio_regs(void) -{ - return (void *)(uintptr_t)IOE_PWRM_BASE_ADDRESS; -} - -uintptr_t soc_read_pmc_base(void) -{ - return (uintptr_t)pmc_mmio_regs(); -} - -uint32_t *soc_pmc_etr_addr(void) -{ - return (uint32_t *)(soc_read_pmc_base() + ETR); -} - -static void pmc_gpe0_different_values(const struct soc_intel_meteorlake_config *config) -{ - bool all_zero = (config->pmc_gpe0_dw0 == 0) && - (config->pmc_gpe0_dw1 == 0) && - (config->pmc_gpe0_dw2 == 0); - - /* Check if all values are different AND not all zero */ - bool all_different = (config->pmc_gpe0_dw0 != config->pmc_gpe0_dw1) && - (config->pmc_gpe0_dw0 != config->pmc_gpe0_dw2) && - (config->pmc_gpe0_dw1 != config->pmc_gpe0_dw2); - - assert(all_different || all_zero); -} - -void soc_get_gpi_gpe_configs(uint8_t *dw0, uint8_t *dw1, uint8_t *dw2) -{ - DEVTREE_CONST struct soc_intel_meteorlake_config *config; - - config = config_of_soc(); - - pmc_gpe0_different_values(config); - - /* Assign to out variable */ - *dw0 = config->pmc_gpe0_dw0; - *dw1 = config->pmc_gpe0_dw1; - *dw2 = config->pmc_gpe0_dw2; -} - -static int rtc_failed(uint32_t gen_pmcon_b) -{ - return !!(gen_pmcon_b & RTC_BATTERY_DEAD); -} - -int soc_get_rtc_failed(void) -{ - const struct chipset_power_state *ps; - - if (acpi_fetch_pm_state(&ps, PS_CLAIMER_RTC) < 0) - return 1; - - return rtc_failed(ps->gen_pmcon_b); -} - -int vbnv_cmos_failed(void) -{ - return rtc_failed(read32(pmc_mmio_regs() + GEN_PMCON_B)); -} - -static inline int deep_s3_enabled(void) -{ - uint32_t deep_s3_pol; - - deep_s3_pol = read32(pmc_mmio_regs() + S3_PWRGATE_POL); - return !!(deep_s3_pol & (S3DC_GATE_SUS | S3AC_GATE_SUS)); -} - -/* Return 0, 3, or 5 to indicate the previous sleep state. */ -int soc_prev_sleep_state(const struct chipset_power_state *ps, int prev_sleep_state) -{ - /* - * Check for any power failure to determine if this a wake from - * S5 because the PCH does not set the WAK_STS bit when waking - * from a true G3 state. - */ - if (!(ps->pm1_sts & WAK_STS) && (ps->gen_pmcon_a & (PWR_FLR | SUS_PWR_FLR))) - prev_sleep_state = ACPI_S5; - - /* - * If waking from S3 determine if deep S3 is enabled. If not, - * need to check both deep sleep well and normal suspend well. - * Otherwise just check deep sleep well. - */ - if (prev_sleep_state == ACPI_S3) { - /* PWR_FLR represents deep sleep power well loss. */ - uint32_t mask = PWR_FLR; - - /* If deep s3 isn't enabled check the suspend well too. */ - if (!deep_s3_enabled()) - mask |= SUS_PWR_FLR; - - if (ps->gen_pmcon_a & mask) - prev_sleep_state = ACPI_S5; - } - - return prev_sleep_state; -} - -void soc_fill_power_state(struct chipset_power_state *ps) -{ - uint8_t *pmc; - - ps->tco1_sts = tco_read_reg(TCO1_STS); - ps->tco2_sts = tco_read_reg(TCO2_STS); - - printk(BIOS_DEBUG, "TCO_STS: %04x %04x\n", ps->tco1_sts, ps->tco2_sts); - - pmc = pmc_mmio_regs(); - ps->gen_pmcon_a = read32(pmc + GEN_PMCON_A); - ps->gen_pmcon_b = read32(pmc + GEN_PMCON_B); - ps->gblrst_cause[0] = read32(pmc + GBLRST_CAUSE0); - ps->gblrst_cause[1] = read32(pmc + GBLRST_CAUSE1); - ps->hpr_cause0 = read32(pmc + HPR_CAUSE0); - - printk(BIOS_DEBUG, "GEN_PMCON: %08x %08x\n", - ps->gen_pmcon_a, ps->gen_pmcon_b); - - printk(BIOS_DEBUG, "GBLRST_CAUSE: %08x %08x\n", - ps->gblrst_cause[0], ps->gblrst_cause[1]); - - printk(BIOS_DEBUG, "HPR_CAUSE0: %08x\n", ps->hpr_cause0); -} - -/* STM Support */ -uint16_t get_pmbase(void) -{ - return (uint16_t)ACPI_BASE_ADDRESS; -} - -/* - * Set which power state system will be after reapplying - * the power (from G3 State) - */ -void pmc_soc_set_afterg3_en(const bool on) -{ - uint8_t reg8; - uint8_t *const pmcbase = pmc_mmio_regs(); - - reg8 = read8(pmcbase + GEN_PMCON_A); - if (on) - reg8 &= ~SLEEP_AFTER_POWER_FAIL; - else - reg8 |= SLEEP_AFTER_POWER_FAIL; - write8(pmcbase + GEN_PMCON_A, reg8); -}