diff options
-rw-r--r-- | src/soc/intel/common/block/acpi/acpi.c | 12 | ||||
-rw-r--r-- | src/soc/intel/common/block/acpi/cpu_hybrid.c | 60 | ||||
-rw-r--r-- | src/soc/intel/common/block/include/intelblocks/acpi.h | 8 |
3 files changed, 78 insertions, 2 deletions
diff --git a/src/soc/intel/common/block/acpi/acpi.c b/src/soc/intel/common/block/acpi/acpi.c index b827c58bc1..53fa90786b 100644 --- a/src/soc/intel/common/block/acpi/acpi.c +++ b/src/soc/intel/common/block/acpi/acpi.c @@ -372,6 +372,11 @@ void generate_t_state_entries(int core, int cores_per_package) static void generate_cppc_entries(int core_id) { + u32 version = CPPC_VERSION_2; + + if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID)) + version = CPPC_VERSION_3; + if (!(CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPPC) && cpuid_eax(6) & CPUID_6_EAX_ISST)) return; @@ -379,12 +384,15 @@ static void generate_cppc_entries(int core_id) /* Generate GCPC package in first logical core */ if (core_id == 0) { struct cppc_config cppc_config; - cpu_init_cppc_config(&cppc_config, CPPC_VERSION_2); + cpu_init_cppc_config(&cppc_config, version); acpigen_write_CPPC_package(&cppc_config); } /* Write _CPC entry for each logical core */ - acpigen_write_CPPC_method(); + if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID)) + acpigen_write_CPPC_hybrid_method(core_id); + else + acpigen_write_CPPC_method(); } __weak void soc_power_states_generation(int core_id, diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c index cbfaed8fd3..70e632900b 100644 --- a/src/soc/intel/common/block/acpi/cpu_hybrid.c +++ b/src/soc/intel/common/block/acpi/cpu_hybrid.c @@ -8,6 +8,9 @@ #include <cpu/x86/lapic.h> #include <cpu/x86/mp.h> +#define CPPC_NOM_FREQ_IDX 22 +#define CPPC_NOM_PERF_IDX 3 + DECLARE_SPIN_LOCK(cpu_lock); static u8 global_cpu_type[CONFIG_MAX_CPUS]; @@ -56,4 +59,61 @@ static void run_set_cpu_type(void *unused) } } +static void acpi_get_cpu_nomi_perf(u16 *small_core_nom_perf, u16 *big_core_nom_perf) +{ + u16 big_core_scal_factor, small_core_scal_factor; + u8 max_non_turbo_ratio = cpu_get_max_non_turbo_ratio(); + + soc_get_scaling_factor(&big_core_scal_factor, &small_core_scal_factor); + + *big_core_nom_perf = (u16)((max_non_turbo_ratio * big_core_scal_factor) / 100); + + *small_core_nom_perf = (u16)((max_non_turbo_ratio * small_core_scal_factor) / 100); +} + +static u16 acpi_get_cpu_nominal_freq(void) +{ + return cpu_get_max_non_turbo_ratio() * cpu_get_bus_frequency(); +} + +/* Updates Nominal Frequency and Nominal Performance */ +static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core_id) +{ + u16 small_core_nom_perf, big_core_nom_perf; + + if (!soc_is_nominal_freq_supported()) + return; + + acpi_get_cpu_nomi_perf(&small_core_nom_perf, &big_core_nom_perf); + + if (global_cpu_type[core_id]) + acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, big_core_nom_perf); + else + acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, + small_core_nom_perf); + + /* Update CPU's nominal frequency */ + acpigen_set_package_element_int(pkg_path, CPPC_NOM_FREQ_IDX, + acpi_get_cpu_nominal_freq()); +} + +void acpigen_write_CPPC_hybrid_method(s32 core_id) +{ + char pkg_path[16]; + + if (core_id == 0) + snprintf(pkg_path, sizeof(pkg_path), CPPC_PACKAGE_NAME, 0); + else + snprintf(pkg_path, sizeof(pkg_path), + CONFIG_ACPI_CPU_STRING "." CPPC_PACKAGE_NAME, 0); + + acpigen_write_method("_CPC", 0); + + /* Update nominal performance and nominal frequency */ + acpigen_cppc_update_nominal_freq_perf(pkg_path, core_id); + acpigen_emit_byte(RETURN_OP); + acpigen_emit_namestring(pkg_path); + acpigen_pop_len(); +} + BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, run_set_cpu_type, NULL); diff --git a/src/soc/intel/common/block/include/intelblocks/acpi.h b/src/soc/intel/common/block/include/intelblocks/acpi.h index 26341451d0..d05ddf3301 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, }; +/* Gets the scaling factor for small and big core */ +void soc_get_scaling_factor(u16 *big_core_scal_factor, u16 *small_core_scal_factor); + +/* Generates ACPI code to define _CPC control method */ +void acpigen_write_CPPC_hybrid_method(int core_id); + /* Forward declare the power state struct here */ struct chipset_power_state; @@ -125,4 +131,6 @@ void sgx_fill_ssdt(void); */ enum core_type get_soc_cpu_type(void); +/* Check if CPU supports Nominal frequency or not */ +bool soc_is_nominal_freq_supported(void); #endif /* _SOC_INTEL_COMMON_BLOCK_ACPI_H_ */ |