From 4b18c0f514d7714877afdf1e9fdd1eebb3e2de75 Mon Sep 17 00:00:00 2001 From: Jeremy Compostella Date: Tue, 10 Dec 2024 17:15:46 -0800 Subject: [PATCH] soc/intel/pantherlake: Add core scaling factors read support This commit adds support for reading core scaling factors via the PCODE mailbox interface. Starting with Lunar Lake, the scaling factor information is centralized in the power control unit (PCU) firmware. In order to keep all firmware in sync, it is recommended to read the scaling factors from the PCU firmware instead of using hard-coded values. The following changes were made: - Updated the Kconfig file to select SOC_INTEL_COMMON_BLOCK_RUNTIME_CORE_SCALING_FACTORS option - Modified the acpi.h header file to export the cpu_perf_eff_type enumeration for CPU performance/efficiency types. - Added a new function to the pantherlake systemagent.c file, soc_read_core_scaling_factors(), which reads the core scaling factors from the PCODE mailbox interface. The pcode READ_CORE_SCALING_FACTOR is presented in document 829201 Panther Lake Processor Mailbox Command. The performance impact on boot time is minimal. It took 12 us to read the scaling factors on a fatcat device. TEST=Successfully read performance and efficient scaling factors on a fatcat board. Change-Id: I7a8e1e66a02e4bf6b1a41277e83c6dec786fe169 Signed-off-by: Jeremy Compostella Reviewed-on: https://review.coreboot.org/c/coreboot/+/85554 Reviewed-by: Bora Guvendik Tested-by: build bot (Jenkins) Reviewed-by: Zhixing Ma --- src/soc/intel/common/block/acpi/cpu_hybrid.c | 5 - .../common/block/include/intelblocks/acpi.h | 6 + src/soc/intel/pantherlake/Kconfig | 9 +- .../pantherlake/include/soc/systemagent.h | 2 + src/soc/intel/pantherlake/systemagent.c | 139 ++++++++++++++++++ 5 files changed, 148 insertions(+), 13 deletions(-) diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c index 36905fe852..2c3b84ceee 100644 --- a/src/soc/intel/common/block/acpi/cpu_hybrid.c +++ b/src/soc/intel/common/block/acpi/cpu_hybrid.c @@ -15,11 +15,6 @@ #define CPPC_NOM_FREQ_IDX 22 #define CPPC_NOM_PERF_IDX 3 -enum cpu_perf_eff_type { - CPU_TYPE_EFF, - CPU_TYPE_PERF, -}; - struct cpu_apic_info_type { /* * Ordered APIC IDs based on core type. diff --git a/src/soc/intel/common/block/include/intelblocks/acpi.h b/src/soc/intel/common/block/include/intelblocks/acpi.h index 9ec8984f45..a3f82481c9 100644 --- a/src/soc/intel/common/block/include/intelblocks/acpi.h +++ b/src/soc/intel/common/block/include/intelblocks/acpi.h @@ -18,6 +18,12 @@ enum core_type { CPUID_UNKNOWN = 0xff, }; +/* CPU Performance Type */ +enum cpu_perf_eff_type { + CPU_TYPE_EFF, + CPU_TYPE_PERF, +}; + unsigned long acpi_create_madt_lapics_with_nmis_hybrid(unsigned long current); /* diff --git a/src/soc/intel/pantherlake/Kconfig b/src/soc/intel/pantherlake/Kconfig index 81dbe8050d..4f6f658fc1 100644 --- a/src/soc/intel/pantherlake/Kconfig +++ b/src/soc/intel/pantherlake/Kconfig @@ -79,6 +79,7 @@ config SOC_INTEL_PANTHERLAKE_BASE select SOC_INTEL_COMMON_BLOCK_PCIE_RTD3 select SOC_INTEL_COMMON_BLOCK_PMC_EPOC select SOC_INTEL_COMMON_BLOCK_POWER_LIMIT + select SOC_INTEL_COMMON_BLOCK_RUNTIME_CORE_SCALING_FACTORS select SOC_INTEL_COMMON_BLOCK_SA select SOC_INTEL_COMMON_BLOCK_SMM select SOC_INTEL_COMMON_BLOCK_SMM_IO_TRAP @@ -248,14 +249,6 @@ config P2SB_2_PCR_BASE_ADDRESS config ECAM_MMCONF_BASE_ADDRESS default 0xe0000000 -config SOC_INTEL_PERFORMANCE_CORE_SCALE_FACTOR - int - default 125 # TODO: Update with PTL data - -config SOC_INTEL_EFFICIENT_CORE_SCALE_FACTOR - int - default 100 # TODO: Update with PTL data - config CPU_BCLK_MHZ int default 100 diff --git a/src/soc/intel/pantherlake/include/soc/systemagent.h b/src/soc/intel/pantherlake/include/soc/systemagent.h index fbe8dd25cc..4139c37aff 100644 --- a/src/soc/intel/pantherlake/include/soc/systemagent.h +++ b/src/soc/intel/pantherlake/include/soc/systemagent.h @@ -23,6 +23,8 @@ #define MCH_DDR_POWER_LIMIT_HI 0x58e4 #define MCH_PKG_POWER_LIMIT_LO 0x59a0 #define MCH_PKG_POWER_LIMIT_HI 0x59a4 +#define PCODE_MAILBOX_DATA 0x5da0 +#define PCODE_MAILBOX_INTERFACE 0x5da4 #define BIOS_RESET_CPL 0x5da8 #define IMRBASE 0x6a40 #define IMRLIMIT 0x6a48 diff --git a/src/soc/intel/pantherlake/systemagent.c b/src/soc/intel/pantherlake/systemagent.c index e7a0701f98..a5a734f02d 100644 --- a/src/soc/intel/pantherlake/systemagent.c +++ b/src/soc/intel/pantherlake/systemagent.c @@ -2,9 +2,12 @@ #include #include +#include #include +#include #include #include +#include #include #include #include @@ -183,6 +186,142 @@ static void configure_tdp(struct device *dev) } } +union pcode_mailbox_command { + struct { + uint32_t command: 8; + uint32_t param1: 8; + uint32_t param2: 13; + uint32_t reserved: 2; + /* + * Run/Busy bit. This bit is set by BIOS to indicate the mailbox buffer is + * ready. pcode will clear this bit after the message is + * consumed. + */ + uint32_t runbusy: 1; + } fields; + uint32_t data; +}; + +union pcode_scaling_factor { + struct { + /* Core scaling factor */ + uint32_t scaling_factor: 16; + /* + * Number of modules with consecutive module id sharing the same scaling + * factor + */ + uint32_t num_equivalent_module: 8; + uint32_t reserved: 8; + } fields; + uint32_t data; +}; + +#define MAILBOX_WAIT_TIMEOUT_US 1000 +#define PCODE_READ_CORE_SCALING_FACTOR_CMD 0x21 + +static bool poll_mailbox_ready(void) +{ + union pcode_mailbox_command cmd; + size_t i; + + for (i = 0; i < MAILBOX_WAIT_TIMEOUT_US; i++) { + cmd.data = MCHBAR32(PCODE_MAILBOX_INTERFACE); + if (!cmd.fields.runbusy) + return true; + udelay(1); + } + return false; +} + +static u16 u88_to_scaling_factor(u16 u88) +{ + unsigned int tmp = (u88 & 0xff) * 100; + unsigned int fraction = tmp / (1 << 8); + + /* Rounding */ + if (((tmp & 0xff) << 1) >= (1 << 8)) + fraction++; + return ((u88 >> 8) * 100) + fraction; +} + +/* + * The following function sends commands to the pcode mailbox interface to read the core scaling + * factors for performance and efficient cores. + * + * The READ_CORE_SCALING_FACTOR command takes a module ID as a parameter. The function iterates + * over all the CPU devices to identify module IDs of different core types (efficient and + * performance). + * + * If no efficient cores are present, no efficient factor is returned. + * + * Return values: + * - CB_ERR_ARG: If any of the input pointers were NULL. + * - CB_ERR: If there was a generic error while reading the scaling factors. + * - CB_SUCCESS: If the scaling factors were read successfully. + */ +enum cb_err soc_read_core_scaling_factors(u16 *performance, u16 *efficient) +{ + extern struct cpu_info cpu_infos[]; + union pcode_mailbox_command cmd = { + .fields = { + .command = PCODE_READ_CORE_SCALING_FACTOR_CMD, + .runbusy = 1 + } + }; + union pcode_scaling_factor res; + bool has_efficient_core = false; + + if (!performance || !efficient) + return CB_ERR_ARG; + + for (size_t i = 0; i < CONFIG_MAX_CPUS; i++) { + struct device *cpu = cpu_infos[i].cpu; + + if (!cpu) + continue; + + if (cpu->path.apic.core_type != CPU_TYPE_PERF) + has_efficient_core = true; + + if (cpu->path.apic.core_type == CPU_TYPE_PERF && *performance) + continue; + + cmd.fields.param1 = cpu->path.apic.module_id; + + if (!poll_mailbox_ready()) { + printk(BIOS_ERR, "pcode mailbox is busy\n"); + return CB_ERR; + } + + MCHBAR32(PCODE_MAILBOX_INTERFACE) = cmd.data; + + if (!poll_mailbox_ready()) { + printk(BIOS_ERR, "pcode command mailbox not completing in time\n"); + return CB_ERR; + } + + res.data = MCHBAR32(PCODE_MAILBOX_DATA); + + if (cpu->path.apic.core_type == CPU_TYPE_PERF) + *performance = u88_to_scaling_factor(res.fields.scaling_factor); + else + *efficient = u88_to_scaling_factor(res.fields.scaling_factor); + + if (*performance && *efficient) + break; + } + + if (!*performance) { + printk(BIOS_ERR, "Could not read performance scaling factor\n"); + return CB_ERR; + } + if (has_efficient_core && !*efficient) { + printk(BIOS_ERR, "Could not read efficient scaling factor\n"); + return CB_ERR; + } + return CB_SUCCESS; +} + /* * SoC implementation *