summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/block/acpi/cpu_hybrid.c121
1 files changed, 64 insertions, 57 deletions
diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c
index 81c4add0b6..a6f9103380 100644
--- a/src/soc/intel/common/block/acpi/cpu_hybrid.c
+++ b/src/soc/intel/common/block/acpi/cpu_hybrid.c
@@ -1,12 +1,15 @@
/* SPDX-License-Identifier: GPL-2.0-or-later */
+#include <acpi/acpi.h>
#include <acpi/acpigen.h>
-#include <intelblocks/acpi.h>
-#include <soc/cpu.h>
-#include <smp/spinlock.h>
-#include <device/device.h>
-#include <device/path.h>
+#include <bootstate.h>
+#include <commonlib/sort.h>
#include <cpu/x86/lapic.h>
#include <cpu/x86/mp.h>
+#include <cpu/cpu.h>
+#include <device/path.h>
+#include <intelblocks/acpi.h>
+#include <soc/cpu.h>
+#include <types.h>
#define CPPC_NOM_FREQ_IDX 22
#define CPPC_NOM_PERF_IDX 3
@@ -16,70 +19,74 @@ enum cpu_perf_eff_type {
CPU_TYPE_PERF,
};
-DECLARE_SPIN_LOCK(cpu_lock);
-static u8 global_cpu_type[CONFIG_MAX_CPUS];
+struct cpu_apic_info_type {
+ /*
+ * Ordered APIC IDs based on core type.
+ * Array begins with Performance Cores' APIC IDs,
+ * then followed by Efficeint Cores's APIC IDs.
+ */
+ int32_t apic_ids[CONFIG_MAX_CPUS];
+
+ /* Total CPU count */
+ uint8_t total_cpu_cnt;
+
+ /*
+ * Total Performance core count. This will be used
+ * to identify the start of Efficient Cores's
+ * APIC ID list
+ */
+ uint8_t perf_cpu_cnt;
+};
-static bool is_perf_core(void)
-{
- return get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE;
-}
+static struct cpu_apic_info_type cpu_apic_info;
-static enum cpu_perf_eff_type get_core_type(void)
+/*
+ * The function orders APIC IDs such that orders first Performance cores and then
+ * Efficient cores' APIC IDs in ascending order. Also calculates total number of
+ * Performance cores and all cores count in the system and populates the information
+ * in the cpu_apic_info sturct.
+ */
+static void acpi_set_hybrid_cpu_apicid_order(void *unused)
{
- return (get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE) ?
- CPU_TYPE_PERF : CPU_TYPE_EFF;
-}
+ size_t perf_core_cnt = 0, eff_core_cnt = 0;
+ int32_t eff_apic_ids[CONFIG_MAX_CPUS] = {0};
+ extern struct cpu_info cpu_infos[];
+ uint32_t i, j = 0;
+
+ for (i = 0; i < ARRAY_SIZE(cpu_apic_info.apic_ids); i++) {
+ if (cpu_infos[i].cpu->path.apic.core_type == CPU_TYPE_PERF)
+ cpu_apic_info.apic_ids[perf_core_cnt++] =
+ cpu_infos[i].cpu->path.apic.apic_id;
+ else
+ eff_apic_ids[eff_core_cnt++] =
+ cpu_infos[i].cpu->path.apic.apic_id;
+ }
-void set_dev_core_type(void)
-{
- struct cpu_info *info = cpu_info();
- info->cpu->path.apic.core_type = get_core_type();
-}
+ if (perf_core_cnt > 1)
+ bubblesort(cpu_apic_info.apic_ids, perf_core_cnt, NUM_ASCENDING);
-static struct device *get_cpu_bus_first_child(void)
-{
- struct device *dev = dev_find_path(NULL, DEVICE_PATH_CPU_CLUSTER);
- assert(dev != NULL);
- return (dev->link_list)->children;
-}
+ for (i = perf_core_cnt; j < eff_core_cnt; i++, j++)
+ cpu_apic_info.apic_ids[i] = eff_apic_ids[j];
-static u32 get_cpu_index(void)
-{
- u32 cpu_index = 0;
- struct device *dev;
- u32 my_apic_id = lapicid();
+ if (eff_core_cnt > 1)
+ bubblesort(&cpu_apic_info.apic_ids[perf_core_cnt], eff_core_cnt, NUM_ASCENDING);
- for (dev = get_cpu_bus_first_child(); dev; dev = dev->sibling)
- if (my_apic_id > dev->path.apic.apic_id)
- cpu_index++;
+ /* Populate total core count */
+ cpu_apic_info.total_cpu_cnt = perf_core_cnt + eff_core_cnt;
- return cpu_index;
+ cpu_apic_info.perf_cpu_cnt = perf_core_cnt;
}
-/*
- * This function determines the type (performance or efficient) of the CPU that
- * is executing it and stores the information (in a thread-safe manner) in an
- * global_cpu_type array.
- * It requires the SoC to implement a function `get_soc_cpu_type()` which will be
- * called in a critical section to determine the type of the executing CPU.
- */
-static void set_cpu_type(void *unused)
+static enum cpu_perf_eff_type get_core_type(void)
{
- spin_lock(&cpu_lock);
- u8 cpu_index = get_cpu_index();
-
- if (is_perf_core())
- global_cpu_type[cpu_index] = CPU_TYPE_PERF;
-
- spin_unlock(&cpu_lock);
+ return (get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE) ?
+ CPU_TYPE_PERF : CPU_TYPE_EFF;
}
-static void run_set_cpu_type(void *unused)
+void set_dev_core_type(void)
{
- if (mp_run_on_all_cpus(set_cpu_type, NULL) != CB_SUCCESS) {
- printk(BIOS_ERR, "cpu_hybrid: Failed to set global_cpu_type with CPU type info\n");
- return;
- }
+ struct cpu_info *info = cpu_info();
+ info->cpu->path.apic.core_type = get_core_type();
}
static void acpi_get_cpu_nomi_perf(u16 *eff_core_nom_perf, u16 *perf_core_nom_perf)
@@ -114,7 +121,7 @@ static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core
acpi_get_cpu_nomi_perf(&eff_core_nom_perf, &perf_core_nom_perf);
- if (global_cpu_type[core_id] == CPU_TYPE_PERF)
+ if (core_id < cpu_apic_info.perf_cpu_cnt)
acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, perf_core_nom_perf);
else
acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX,
@@ -144,4 +151,4 @@ void acpigen_write_CPPC_hybrid_method(s32 core_id)
acpigen_pop_len();
}
-BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, run_set_cpu_type, NULL);
+BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, acpi_set_hybrid_cpu_apicid_order, NULL);