blob: 2d1f375c9da57dc67543b60fbc23565147a272b8 [file] [log] [blame]
Jonathan Zhangd80e6f22023-01-25 11:35:03 -08001/* SPDX-License-Identifier: GPL-2.0-only */
2
3#include <acpi/acpigen.h>
4#include <arch/smp/mpspec.h>
Felix Held97439ec2023-06-05 19:30:23 +02005#include <arch/vga.h>
Jonathan Zhangd80e6f22023-01-25 11:35:03 -08006#include <assert.h>
7#include <cbmem.h>
8#include <cpu/intel/turbo.h>
9#include <device/mmio.h>
10#include <device/pci.h>
11#include <intelblocks/acpi.h>
12#include <intelblocks/cpulib.h>
13#include <intelblocks/pmclib.h>
14#include <soc/acpi.h>
15#include <soc/iomap.h>
16#include <soc/msr.h>
17#include <soc/pci_devs.h>
18#include <soc/pm.h>
19#include <soc/soc_util.h>
20#include <soc/util.h>
21#include <hob_iiouds.h>
22
23int soc_madt_sci_irq_polarity(int sci)
24{
25 if (sci >= 20)
26 return MP_IRQ_POLARITY_LOW;
27 else
28 return MP_IRQ_POLARITY_HIGH;
29}
30
31uint32_t soc_read_sci_irq_select(void)
32{
33 /* PMC controller is hidden - hence PWRMBASE can't be accessbile using PCI cfg space */
34 uintptr_t pmc_bar = PCH_PWRM_BASE_ADDRESS;
35 return read32((void *)pmc_bar + PMC_ACPI_CNT);
36}
37
38void soc_fill_fadt(acpi_fadt_t *fadt)
39{
40 const uint16_t pmbase = ACPI_BASE_ADDRESS;
41
42 fadt->FADT_MinorVersion = 1;
43 fadt->pm_tmr_blk = pmbase + PM1_TMR;
44 fadt->pm_tmr_len = 4;
45 /* Clear flags set by common/block/acpi/acpi.c acpi_fill_fadt() */
46 fadt->flags &= ~ACPI_FADT_SEALED_CASE;
47
48 fadt->preferred_pm_profile = PM_ENTERPRISE_SERVER;
49 fadt->pm2_cnt_blk = pmbase + PM2_CNT;
50 fadt->pm2_cnt_len = 1;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080051
Kyösti Mälkki88decca2023-04-28 07:04:34 +030052 /* PM Extended Registers */
53 fill_fadt_extended_pm_io(fadt);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080054}
55
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080056/* TODO: See if we can use the common generate_p_state_entries */
57void soc_power_states_generation(int core, int cores_per_package)
58{
59 int ratio_min, ratio_max, ratio_turbo, ratio_step;
60 int coord_type, power_max, power_unit, num_entries;
61 int ratio, power, clock, clock_max;
62 msr_t msr;
63
64 /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
65 msr = rdmsr(MSR_MISC_PWR_MGMT);
66 if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
67 coord_type = SW_ANY;
68 else
69 coord_type = HW_ALL;
70
71 /* Get bus ratio limits and calculate clock speeds */
72 msr = rdmsr(MSR_PLATFORM_INFO);
73 ratio_min = (msr.hi >> (40 - 32)) & 0xff; /* Max Efficiency Ratio */
74
75 /* Determine if this CPU has configurable TDP */
76 if (cpu_config_tdp_levels()) {
77 /* Set max ratio to nominal TDP ratio */
78 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
79 ratio_max = msr.lo & 0xff;
80 } else {
81 /* Max Non-Turbo Ratio */
82 ratio_max = (msr.lo >> 8) & 0xff;
83 }
84 clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ;
85
86 /* Calculate CPU TDP in mW */
87 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
88 power_unit = 2 << ((msr.lo & 0xf) - 1);
89 msr = rdmsr(MSR_PKG_POWER_SKU);
90 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
91
92 /* Write _PCT indicating use of FFixedHW */
93 acpigen_write_empty_PCT();
94
95 /* Write _PPC with no limit on supported P-state */
96 acpigen_write_PPC_NVS();
97
98 /* Write PSD indicating configured coordination type */
99 acpigen_write_PSD_package(core, 1, coord_type);
100
101 /* Add P-state entries in _PSS table */
102 acpigen_write_name("_PSS");
103
104 /* Determine ratio points */
105 ratio_step = PSS_RATIO_STEP;
106 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
107 if (num_entries > PSS_MAX_ENTRIES) {
108 ratio_step += 1;
109 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
110 }
111
112 /* P[T] is Turbo state if enabled */
113 if (get_turbo_state() == TURBO_ENABLED) {
114 /* _PSS package count including Turbo */
115 acpigen_write_package(num_entries + 2);
116
117 msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
118 ratio_turbo = msr.lo & 0xff;
119
120 /* Add entry for Turbo ratio */
121 acpigen_write_PSS_package(clock_max + 1, /* MHz */
122 power_max, /* mW */
123 PSS_LATENCY_TRANSITION, /* lat1 */
124 PSS_LATENCY_BUSMASTER, /* lat2 */
125 ratio_turbo << 8, /* control */
126 ratio_turbo << 8); /* status */
127 } else {
128 /* _PSS package count without Turbo */
129 acpigen_write_package(num_entries + 1);
130 }
131
132 /* First regular entry is max non-turbo ratio */
133 acpigen_write_PSS_package(clock_max, /* MHz */
134 power_max, /* mW */
135 PSS_LATENCY_TRANSITION, /* lat1 */
136 PSS_LATENCY_BUSMASTER, /* lat2 */
137 ratio_max << 8, /* control */
138 ratio_max << 8); /* status */
139
140 /* Generate the remaining entries */
141 for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min;
142 ratio -= ratio_step) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800143 /* Calculate power at this ratio */
144 power = common_calculate_power_ratio(power_max, ratio_max, ratio);
145 clock = ratio * CONFIG_CPU_BCLK_MHZ;
146 // clock = 1;
147 acpigen_write_PSS_package(clock, /* MHz */
148 power, /* mW */
149 PSS_LATENCY_TRANSITION, /* lat1 */
150 PSS_LATENCY_BUSMASTER, /* lat2 */
151 ratio << 8, /* control */
152 ratio << 8); /* status */
153 }
154
155 /* Fix package length */
156 acpigen_pop_len();
157}
158
159unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current)
160{
161 struct device *cpu;
162 uint8_t num_cpus = 0;
163
164 for (cpu = all_devices; cpu; cpu = cpu->next) {
165 if ((cpu->path.type != DEVICE_PATH_APIC)
Arthur Heymans7fcd4d52023-08-24 15:12:19 +0200166 || (cpu->upstream->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800167 continue;
168 }
169 if (!cpu->enabled)
170 continue;
Kyösti Mälkki2e9f0d32023-04-07 23:05:46 +0300171 current = acpi_create_madt_one_lapic(current, num_cpus, cpu->path.apic.apic_id);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800172 num_cpus++;
173 }
174
175 return current;
176}
177
178unsigned long acpi_fill_cedt(unsigned long current)
179{
180 const IIO_UDS *hob = get_iio_uds();
181 union uid {
182 uint32_t data;
183 struct {
184 uint8_t byte0;
185 uint8_t byte1;
186 uint8_t byte2;
187 uint8_t byte3;
188 };
189 } cxl_uid;
190 u32 cxl_ver;
191 u64 base;
192
193 cxl_uid.byte0 = 'C';
194 cxl_uid.byte1 = 'X';
195 /* Loop through all sockets and stacks, add CHBS for each CXL IIO stack */
Patrick Rudolphac028572023-07-14 17:44:33 +0200196 for (uint8_t socket = 0, iio = 0; iio < hob->PlatformData.numofIIO; ++socket) {
197 if (!soc_cpu_is_enabled(socket))
198 continue;
199 iio++;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800200 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
Patrick Rudolphac028572023-07-14 17:44:33 +0200201 const STACK_RES *ri;
202 ri = &hob->PlatformData.IIO_resource[socket].StackRes[x];
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800203 if (!is_iio_cxl_stack_res(ri))
204 continue;
205 /* uid needs to match with ACPI CXL device ID, eg. acpi/iiostack.asl */
Patrick Rudolphac028572023-07-14 17:44:33 +0200206 cxl_uid.byte2 = socket + '0';
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800207 cxl_uid.byte3 = x + '0';
208 cxl_ver = ACPI_CEDT_CHBS_CXL_VER_1_1;
209 base = ri->Mmio32Base; /* DP RCRB base */
210 current += acpi_create_cedt_chbs((acpi_cedt_chbs_t *)current,
211 cxl_uid.data, cxl_ver, base);
212 }
213 }
214
215 return current;
216}