Jérémy Compostella has submitted this change. ( https://review.coreboot.org/c/coreboot/+/85554?usp=email )
Change subject: soc/intel/pantherlake: Add core scaling factors read support ......................................................................
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 jeremy.compostella@intel.com Reviewed-on: https://review.coreboot.org/c/coreboot/+/85554 Reviewed-by: Bora Guvendik bora.guvendik@intel.com Tested-by: build bot (Jenkins) no-reply@coreboot.org Reviewed-by: Zhixing Ma zhixing.ma@intel.com --- M src/soc/intel/common/block/acpi/cpu_hybrid.c M src/soc/intel/common/block/include/intelblocks/acpi.h M src/soc/intel/pantherlake/Kconfig M src/soc/intel/pantherlake/include/soc/systemagent.h M src/soc/intel/pantherlake/systemagent.c 5 files changed, 148 insertions(+), 13 deletions(-)
Approvals: Bora Guvendik: Looks good to me, approved Zhixing Ma: Looks good to me, but someone else must approve build bot (Jenkins): Verified
diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c index 36905fe..2c3b84c 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 9ec8984..a3f8248 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 @@ 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 81dbe80..4f6f658 100644 --- a/src/soc/intel/pantherlake/Kconfig +++ b/src/soc/intel/pantherlake/Kconfig @@ -79,6 +79,7 @@ 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 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 fbe8dd2..4139c37 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 e7a0701..a5a734f 100644 --- a/src/soc/intel/pantherlake/systemagent.c +++ b/src/soc/intel/pantherlake/systemagent.c @@ -2,9 +2,12 @@
#include <arch/ioapic.h> #include <console/console.h> +#include <cpu/cpu.h> #include <cpu/x86/msr.h> +#include <delay.h> #include <device/device.h> #include <device/pci.h> +#include <intelblocks/acpi.h> #include <intelblocks/cpulib.h> #include <intelblocks/msr.h> #include <intelblocks/power_limit.h> @@ -183,6 +186,142 @@ } }
+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 *