blob: 9a7b768de60077597ec80654e39cd2fe1137d2e3 [file] [log] [blame]
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +05301/* SPDX-License-Identifier: GPL-2.0-or-later */
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +05302#include <acpi/acpi.h>
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +05303#include <acpi/acpigen.h>
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +05304#include <bootstate.h>
5#include <commonlib/sort.h>
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +05306#include <cpu/x86/lapic.h>
7#include <cpu/x86/mp.h>
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +05308#include <cpu/cpu.h>
9#include <device/path.h>
10#include <intelblocks/acpi.h>
11#include <soc/cpu.h>
12#include <types.h>
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +053013
Sridhar Siricilla11736122021-11-15 17:12:49 +053014#define CPPC_NOM_FREQ_IDX 22
15#define CPPC_NOM_PERF_IDX 3
16
Sridhar Siricilla51c75ac2022-01-29 14:26:22 +053017enum cpu_perf_eff_type {
Sridhar Siricilla4c3014f2023-01-03 11:29:08 +053018 CPU_TYPE_EFF,
19 CPU_TYPE_PERF,
Sridhar Siricilla51c75ac2022-01-29 14:26:22 +053020};
21
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +053022struct cpu_apic_info_type {
23 /*
24 * Ordered APIC IDs based on core type.
25 * Array begins with Performance Cores' APIC IDs,
26 * then followed by Efficeint Cores's APIC IDs.
27 */
28 int32_t apic_ids[CONFIG_MAX_CPUS];
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +053029
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +053030 /* Total CPU count */
Sridhar Siricilla02b39ef2023-04-09 17:40:43 +053031 uint16_t total_cpu_cnt;
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +053032
33 /*
34 * Total Performance core count. This will be used
35 * to identify the start of Efficient Cores's
36 * APIC ID list
37 */
Sridhar Siricilla02b39ef2023-04-09 17:40:43 +053038 uint16_t perf_cpu_cnt;
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +053039};
40
41static struct cpu_apic_info_type cpu_apic_info;
42
43/*
44 * The function orders APIC IDs such that orders first Performance cores and then
45 * Efficient cores' APIC IDs in ascending order. Also calculates total number of
46 * Performance cores and all cores count in the system and populates the information
47 * in the cpu_apic_info sturct.
48 */
49static void acpi_set_hybrid_cpu_apicid_order(void *unused)
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +053050{
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +053051 size_t perf_core_cnt = 0, eff_core_cnt = 0;
52 int32_t eff_apic_ids[CONFIG_MAX_CPUS] = {0};
53 extern struct cpu_info cpu_infos[];
54 uint32_t i, j = 0;
55
56 for (i = 0; i < ARRAY_SIZE(cpu_apic_info.apic_ids); i++) {
57 if (cpu_infos[i].cpu->path.apic.core_type == CPU_TYPE_PERF)
58 cpu_apic_info.apic_ids[perf_core_cnt++] =
59 cpu_infos[i].cpu->path.apic.apic_id;
60 else
61 eff_apic_ids[eff_core_cnt++] =
62 cpu_infos[i].cpu->path.apic.apic_id;
63 }
64
65 if (perf_core_cnt > 1)
66 bubblesort(cpu_apic_info.apic_ids, perf_core_cnt, NUM_ASCENDING);
67
68 for (i = perf_core_cnt; j < eff_core_cnt; i++, j++)
69 cpu_apic_info.apic_ids[i] = eff_apic_ids[j];
70
71 if (eff_core_cnt > 1)
72 bubblesort(&cpu_apic_info.apic_ids[perf_core_cnt], eff_core_cnt, NUM_ASCENDING);
73
74 /* Populate total core count */
75 cpu_apic_info.total_cpu_cnt = perf_core_cnt + eff_core_cnt;
76
77 cpu_apic_info.perf_cpu_cnt = perf_core_cnt;
Sridahr Siricillacd1cd8d2021-11-11 01:29:40 +053078}
79
Sridhar Siricilla7301cfa2023-01-19 18:50:09 +053080static unsigned long acpi_create_madt_lapics_hybrid(unsigned long current)
81{
82 size_t index;
83
Kyösti Mälkki2e9f0d32023-04-07 23:05:46 +030084 for (index = 0; index < cpu_apic_info.total_cpu_cnt; index++)
85 current = acpi_create_madt_one_lapic(current, index,
86 cpu_apic_info.apic_ids[index]);
Sridhar Siricilla7301cfa2023-01-19 18:50:09 +053087
88 return current;
89}
90
91unsigned long acpi_create_madt_lapics_with_nmis_hybrid(unsigned long current)
92{
Sridhar Siricilla7301cfa2023-01-19 18:50:09 +053093 current = acpi_create_madt_lapics_hybrid(current);
Kyösti Mälkki9ac1fb72023-04-07 22:39:53 +030094 current = acpi_create_madt_lapic_nmis(current);
Sridhar Siricilla7301cfa2023-01-19 18:50:09 +053095 return current;
96}
97
Sridhar Siricilla1b04e812023-03-30 09:51:28 +053098static enum cpu_perf_eff_type get_core_type(void)
99{
100 return (get_soc_cpu_type() == CPUID_CORE_TYPE_INTEL_CORE) ?
101 CPU_TYPE_PERF : CPU_TYPE_EFF;
102}
103
104void set_dev_core_type(void)
105{
106 struct cpu_info *info = cpu_info();
107 info->cpu->path.apic.core_type = get_core_type();
108}
109
Sridhar Siricilla4c3014f2023-01-03 11:29:08 +0530110static void acpi_get_cpu_nomi_perf(u16 *eff_core_nom_perf, u16 *perf_core_nom_perf)
Sridhar Siricilla11736122021-11-15 17:12:49 +0530111{
Sridhar Siricilla11736122021-11-15 17:12:49 +0530112 u8 max_non_turbo_ratio = cpu_get_max_non_turbo_ratio();
113
Sridhar Siricillad9c82692023-01-05 17:08:17 +0530114 _Static_assert(CONFIG_SOC_INTEL_PERFORMANCE_CORE_SCALE_FACTOR != 0,
115 "CONFIG_SOC_INTEL_PERFORMANCE_CORE_SCALE_FACTOR must not be zero");
Sridhar Siricilla11736122021-11-15 17:12:49 +0530116
Sridhar Siricillad9c82692023-01-05 17:08:17 +0530117 _Static_assert(CONFIG_SOC_INTEL_EFFICIENT_CORE_SCALE_FACTOR != 0,
118 "CONFIG_SOC_INTEL_EFFICIENT_CORE_SCALE_FACTOR must not be zero");
Sridhar Siricilla11736122021-11-15 17:12:49 +0530119
Sridhar Siricillad9c82692023-01-05 17:08:17 +0530120 *perf_core_nom_perf = (u16)((max_non_turbo_ratio *
121 CONFIG_SOC_INTEL_PERFORMANCE_CORE_SCALE_FACTOR) / 100);
122
123 *eff_core_nom_perf = (u16)((max_non_turbo_ratio *
124 CONFIG_SOC_INTEL_EFFICIENT_CORE_SCALE_FACTOR) / 100);
Sridhar Siricilla11736122021-11-15 17:12:49 +0530125}
126
127static u16 acpi_get_cpu_nominal_freq(void)
128{
129 return cpu_get_max_non_turbo_ratio() * cpu_get_bus_frequency();
130}
131
132/* Updates Nominal Frequency and Nominal Performance */
133static void acpigen_cppc_update_nominal_freq_perf(const char *pkg_path, s32 core_id)
134{
Sridhar Siricilla4c3014f2023-01-03 11:29:08 +0530135 u16 eff_core_nom_perf, perf_core_nom_perf;
Sridhar Siricilla11736122021-11-15 17:12:49 +0530136
137 if (!soc_is_nominal_freq_supported())
138 return;
139
Sridhar Siricilla4c3014f2023-01-03 11:29:08 +0530140 acpi_get_cpu_nomi_perf(&eff_core_nom_perf, &perf_core_nom_perf);
Sridhar Siricilla11736122021-11-15 17:12:49 +0530141
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +0530142 if (core_id < cpu_apic_info.perf_cpu_cnt)
Sridhar Siricilla4c3014f2023-01-03 11:29:08 +0530143 acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX, perf_core_nom_perf);
Sridhar Siricilla11736122021-11-15 17:12:49 +0530144 else
145 acpigen_set_package_element_int(pkg_path, CPPC_NOM_PERF_IDX,
Sridhar Siricilla4c3014f2023-01-03 11:29:08 +0530146 eff_core_nom_perf);
Sridhar Siricilla11736122021-11-15 17:12:49 +0530147
148 /* Update CPU's nominal frequency */
149 acpigen_set_package_element_int(pkg_path, CPPC_NOM_FREQ_IDX,
150 acpi_get_cpu_nominal_freq());
151}
152
153void acpigen_write_CPPC_hybrid_method(s32 core_id)
154{
155 char pkg_path[16];
156
157 if (core_id == 0)
158 snprintf(pkg_path, sizeof(pkg_path), CPPC_PACKAGE_NAME, 0);
159 else
160 snprintf(pkg_path, sizeof(pkg_path),
Felix Heldf0a8b042023-05-12 15:55:06 +0200161 "\\_SB." CONFIG_ACPI_CPU_STRING "." CPPC_PACKAGE_NAME, 0);
Sridhar Siricilla11736122021-11-15 17:12:49 +0530162
163 acpigen_write_method("_CPC", 0);
164
165 /* Update nominal performance and nominal frequency */
166 acpigen_cppc_update_nominal_freq_perf(pkg_path, core_id);
167 acpigen_emit_byte(RETURN_OP);
168 acpigen_emit_namestring(pkg_path);
169 acpigen_pop_len();
170}
171
Sridhar Siricillaf8ac3dd2023-03-30 11:25:36 +0530172BOOT_STATE_INIT_ENTRY(BS_DEV_INIT_CHIPS, BS_ON_EXIT, acpi_set_hybrid_cpu_apicid_order, NULL);