From e3c74ccd773133247a36ae299ca3ca3b1c059130 Mon Sep 17 00:00:00 2001 From: Naresh Solanki Date: Fri, 7 Mar 2025 00:55:54 +0530 Subject: [PATCH] soc/amd/common/cpu: smbios: CPU frequency & voltage Determine CPU frequency & voltage for use in smbios type 4 table. Reference: AMD PPR 57254 v1.59 Section 2.1.15 CPUID Instruction TEST=Build for glinda SoC & verify output to reflect CPU frequency & voltage. Sample Output: dmidecode -t ... Voltage: 1.2 V ... Current Speed: 2600 MHz ... Change-Id: Ibd7c7f1e299a0a8d294e7e30ae3130faae16ae22 Signed-off-by: Naresh Solanki Reviewed-on: https://review.coreboot.org/c/coreboot/+/86757 Reviewed-by: Felix Held Tested-by: build bot (Jenkins) --- src/soc/amd/common/block/cpu/noncar/cpu.c | 51 +++++++++++++++++++++++ 1 file changed, 51 insertions(+) diff --git a/src/soc/amd/common/block/cpu/noncar/cpu.c b/src/soc/amd/common/block/cpu/noncar/cpu.c index 74b29cdb66..e67d669bb6 100644 --- a/src/soc/amd/common/block/cpu/noncar/cpu.c +++ b/src/soc/amd/common/block/cpu/noncar/cpu.c @@ -9,8 +9,59 @@ #include #include #include +#include #include +#define UNSUPPORTED 0 + +#define UNINITIALIZED ((uint64_t)-1) + +static union pstate_msr get_pstate0_msr(void) +{ + static union pstate_msr pstate_reg = { .raw = UNINITIALIZED }; + + struct cpuid_result res; + + /* Check if we have already determined P-state support */ + if (pstate_reg.raw == UNINITIALIZED) { + if (cpu_cpuid_extended_level() < CPUID_EXT_PM) { + pstate_reg.pstate_en = UNSUPPORTED; + return pstate_reg; + } + + res = cpuid(CPUID_EXT_PM); + + if (!(res.edx & BIT(7))) { /* Hardware P-state control */ + pstate_reg.pstate_en = UNSUPPORTED; + return pstate_reg; + } + + pstate_reg.raw = rdmsr(PSTATE_MSR(get_pstate_0_reg())).raw; + } + + return pstate_reg; +} + +unsigned int smbios_cpu_get_current_speed_mhz(void) +{ + union pstate_msr pstate_reg = get_pstate0_msr(); + + if (!pstate_reg.pstate_en) + return 0; + + return get_pstate_core_freq(pstate_reg); +} + +unsigned int smbios_cpu_get_voltage(void) +{ + union pstate_msr pstate_reg = get_pstate0_msr(); + + if (!pstate_reg.pstate_en) + return 0; + + return get_pstate_core_uvolts(pstate_reg) / 100000; /* uV to (10 * V) */ +} + uint32_t get_pstate_0_reg(void) { return 0;