summaryrefslogtreecommitdiff
path: root/src/soc
diff options
context:
space:
mode:
Diffstat (limited to 'src/soc')
-rw-r--r--src/soc/intel/common/block/acpi/Kconfig5
-rw-r--r--src/soc/intel/common/block/acpi/Makefile.inc1
-rw-r--r--src/soc/intel/common/block/acpi/cpu_hybrid.c59
-rw-r--r--src/soc/intel/common/block/include/intelblocks/acpi.h17
4 files changed, 82 insertions, 0 deletions
diff --git a/src/soc/intel/common/block/acpi/Kconfig b/src/soc/intel/common/block/acpi/Kconfig
index 07e9bea8d3..e21584c073 100644
--- a/src/soc/intel/common/block/acpi/Kconfig
+++ b/src/soc/intel/common/block/acpi/Kconfig
@@ -44,4 +44,9 @@ config SOC_INTEL_COMMON_BLOCK_ACPI_CPPC
help
Generate CPPC entries for Intel SpeedShift
+config SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID
+ bool
+ help
+ Defines hybrid CPU specific ACPI helper functions.
+
endif
diff --git a/src/soc/intel/common/block/acpi/Makefile.inc b/src/soc/intel/common/block/acpi/Makefile.inc
index a6eb80db36..0286d942dc 100644
--- a/src/soc/intel/common/block/acpi/Makefile.inc
+++ b/src/soc/intel/common/block/acpi/Makefile.inc
@@ -5,3 +5,4 @@ ramstage-$(CONFIG_ACPI_BERT) += acpi_bert.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_ACPI_WAKE_SOURCE) += acpi_wake_source.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_PEP) += pep.c
ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_SGX_ENABLE) += sgx.c
+ramstage-$(CONFIG_SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID) += cpu_hybrid.c
diff --git a/src/soc/intel/common/block/acpi/cpu_hybrid.c b/src/soc/intel/common/block/acpi/cpu_hybrid.c
new file mode 100644
index 0000000000..cbfaed8fd3
--- /dev/null
+++ b/src/soc/intel/common/block/acpi/cpu_hybrid.c
@@ -0,0 +1,59 @@
+/* SPDX-License-Identifier: GPL-2.0-or-later */
+#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 <cpu/x86/lapic.h>
+#include <cpu/x86/mp.h>
+
+DECLARE_SPIN_LOCK(cpu_lock);
+static u8 global_cpu_type[CONFIG_MAX_CPUS];
+
+static bool is_big_core(void)
+{
+ return get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE;
+}
+
+static u32 get_cpu_index(void)
+{
+ u32 cpu_index = 0;
+ struct device *dev;
+ u32 my_apic_id = lapicid();
+
+ for (dev = dev_find_lapic(0); dev; dev = dev->next) {
+ if (my_apic_id > dev->path.apic.apic_id)
+ cpu_index++;
+ }
+
+ return cpu_index;
+}
+
+/*
+ * This function determines the type (big or small) 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)
+{
+ spin_lock(&cpu_lock);
+ u8 cpu_index = get_cpu_index();
+
+ if (is_big_core())
+ global_cpu_type[cpu_index] = 1;
+
+ spin_unlock(&cpu_lock);
+}
+
+static void run_set_cpu_type(void *unused)
+{
+ 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;
+ }
+}
+
+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 2d3136eae6..26341451d0 100644
--- a/src/soc/intel/common/block/include/intelblocks/acpi.h
+++ b/src/soc/intel/common/block/include/intelblocks/acpi.h
@@ -9,6 +9,15 @@
#include <soc/pm.h>
#include <stdint.h>
+/* CPU Types */
+enum core_type {
+ CPUID_RESERVED_1 = 0x10,
+ CPUID_CORE_TYPE_INTEL_ATOM = 0x20,
+ CPUID_RESERVED_2 = 0x30,
+ CPUID_CORE_TYPE_INTEL_CORE = 0x40,
+ CPUID_UNKNOWN = 0xff,
+};
+
/* Forward declare the power state struct here */
struct chipset_power_state;
@@ -108,4 +117,12 @@ void generate_acpi_power_engine_with_lpm(const struct soc_pmc_lpm *lpm);
/* Fill SSDT for SGX status, EPC base and length */
void sgx_fill_ssdt(void);
+/*
+ * This function returns the CPU type (big or small) of the CPU that it is executing
+ * on. It is designed to be called after MP initialization. If the SoC selects
+ * SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID, then this function must be implemented,
+ * and will be called from set_cpu_type().
+ */
+enum core_type get_soc_cpu_type(void);
+
#endif /* _SOC_INTEL_COMMON_BLOCK_ACPI_H_ */