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 *