summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/intel/common/block/acpi/acpi.c12
-rw-r--r--src/soc/intel/common/block/acpi/cpu_hybrid.c60
-rw-r--r--src/soc/intel/common/block/include/intelblocks/acpi.h8
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_ */