blob: 2b820f123cfa9b84c90a18f53fe510128c9e5d21 [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>
5#include <assert.h>
6#include <cbmem.h>
7#include <cpu/intel/turbo.h>
8#include <device/mmio.h>
9#include <device/pci.h>
10#include <intelblocks/acpi.h>
11#include <intelblocks/cpulib.h>
12#include <intelblocks/pmclib.h>
13#include <soc/acpi.h>
14#include <soc/iomap.h>
15#include <soc/msr.h>
16#include <soc/pci_devs.h>
17#include <soc/pm.h>
18#include <soc/soc_util.h>
19#include <soc/util.h>
20#include <hob_iiouds.h>
21
22int soc_madt_sci_irq_polarity(int sci)
23{
24 if (sci >= 20)
25 return MP_IRQ_POLARITY_LOW;
26 else
27 return MP_IRQ_POLARITY_HIGH;
28}
29
30uint32_t soc_read_sci_irq_select(void)
31{
32 /* PMC controller is hidden - hence PWRMBASE can't be accessbile using PCI cfg space */
33 uintptr_t pmc_bar = PCH_PWRM_BASE_ADDRESS;
34 return read32((void *)pmc_bar + PMC_ACPI_CNT);
35}
36
37void soc_fill_fadt(acpi_fadt_t *fadt)
38{
39 const uint16_t pmbase = ACPI_BASE_ADDRESS;
40
41 fadt->FADT_MinorVersion = 1;
42 fadt->pm_tmr_blk = pmbase + PM1_TMR;
43 fadt->pm_tmr_len = 4;
44 /* Clear flags set by common/block/acpi/acpi.c acpi_fill_fadt() */
45 fadt->flags &= ~ACPI_FADT_SEALED_CASE;
46
47 fadt->preferred_pm_profile = PM_ENTERPRISE_SERVER;
48 fadt->pm2_cnt_blk = pmbase + PM2_CNT;
49 fadt->pm2_cnt_len = 1;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080050
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080051 /* PM2 Control Registers */
52 fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
53 fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
54 fadt->x_pm2_cnt_blk.bit_offset = 0;
Kyösti Mälkkie599d432023-04-28 09:39:24 +030055 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
56 fadt->x_pm2_cnt_blk.addrl = fadt->pm2_cnt_blk;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080057 fadt->x_pm2_cnt_blk.addrh = 0x0;
58
59 /* PM1 Timer Register */
60 fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
61 fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
62 fadt->x_pm_tmr_blk.bit_offset = 0;
63 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
Kyösti Mälkkie599d432023-04-28 09:39:24 +030064 fadt->x_pm_tmr_blk.addrl = fadt->pm_tmr_blk;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080065 fadt->x_pm_tmr_blk.addrh = 0x0;
66
67 fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
68 fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
69 fadt->x_gpe0_blk.bit_offset = 0;
70 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
71 fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
72 fadt->x_gpe0_blk.addrh = 0x0;
73
74 fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
75 fadt->x_gpe1_blk.bit_width = fadt->gpe1_blk_len * 8;
76 fadt->x_gpe1_blk.bit_offset = 0;
77 fadt->x_gpe1_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
78 fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
79 fadt->x_gpe1_blk.addrh = 0x0;
80}
81
Patrick Rudolph6e6832d2023-04-04 09:37:30 +020082static void create_dsdt_iou_pci_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri,
83 bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080084{
85 /*
86 Stacks 0 (TYPE_UBOX_IIO)
87 Scope: PC<socket><stack>, ResourceTemplate: P0RS
88 Stacks 1 .. 5 (TYPE_UBOX_IIO)
89 Scope: PC<socket><stack>, ResourceTemplate: RBRS
90 */
91
92 /* Write ResourceTemplate resource name */
93 char tres[16];
94 snprintf(tres, sizeof(tres), "PT%d%X", socket, stack);
95 acpigen_write_name(tres);
96
97 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
98 socket, stack);
99
100 acpigen_write_resourcetemplate_header();
101
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800102 /* Bus Resource */
103 if (stack_enabled) {
104 /* For stack with CXL device, the PCIe bus resource is BusBase only. */
105 if (is_iio_cxl_stack_res(ri))
106 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
107 else
108 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusLimit, 0x0,
109 (ri->BusLimit - ri->BusBase + 1));
110 } else {
111 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
112 }
113
114 /* Additional IO resources on socket 0 bus 0 */
115 if (socket == 0 && stack == 0) {
116 /* ACPI 6.4.2.5 I/O Port Descriptor */
117 acpigen_write_io16(0xCF8, 0xCFF, 0x1, 0x8, 1);
118
119 /* IO decode CF8-CFF */
120 acpigen_resource_word(1, 0xc, 0x3, 0, 0x0000, 0x03AF, 0, 0x03B0);
121 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03E0, 0x0CF7, 0, 0x0918);
122 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03B0, 0x03BB, 0, 0x000C);
123 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03C0, 0x03DF, 0, 0x0020);
124 }
125
126 /* IO resource */
127 if (stack_enabled) {
128 acpigen_resource_word(1, 0xc, 0x3, 0, ri->PciResourceIoBase,
129 ri->PciResourceIoLimit, 0x0,
130 (ri->PciResourceIoLimit - ri->PciResourceIoBase + 1));
131
132 /* Additional Mem32 resources on socket 0 bus 0 */
133 if (socket == 0 && stack == 0) {
134 acpigen_resource_dword(0, 0xc, 3, 0, VGA_BASE_ADDRESS,
135 (VGA_BASE_ADDRESS + VGA_BASE_SIZE - 1), 0x0,
136 VGA_BASE_SIZE);
137 acpigen_resource_dword(0, 0xc, 1, 0, SPI_BASE_ADDRESS,
138 (SPI_BASE_ADDRESS + SPI_BASE_SIZE - 1), 0x0,
139 SPI_BASE_SIZE);
140 }
141
142 /* Mem32 resource */
143 acpigen_resource_dword(
144 0, 0xc, 1, 0, ri->PciResourceMem32Base, ri->PciResourceMem32Limit, 0x0,
145 (ri->PciResourceMem32Limit - ri->PciResourceMem32Base + 1));
146
147 /* Mem64 resource */
148 acpigen_resource_qword(
149 0, 0xc, 1, 0, ri->PciResourceMem64Base, ri->PciResourceMem64Limit, 0x0,
150 (ri->PciResourceMem64Limit - ri->PciResourceMem64Base + 1));
151 } else {
152 /* Zeroed IO resource */
153 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
154
155 /* Zeroed Mem32 resource */
156 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
157
158 /* Zeroed Mem64 resource */
159 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
160 }
161
162 acpigen_write_resourcetemplate_footer();
163}
164
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200165static void create_dsdt_iou_cxl_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri, bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800166{
167 /*
168 Stacks 1 .. 5 (TYPE_UBOX_IIO)
169 Scope: CX<socket><stack>, ResourceTemplate: RBRS
170 */
171 /* write ResourceTemplate resource name */
172 char tres[16];
173 snprintf(tres, sizeof(tres), "CT%d%X", socket, stack);
174 acpigen_write_name(tres);
175
176 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
177 socket, stack);
178
179 acpigen_write_resourcetemplate_header();
180
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200181 if (stack_enabled) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800182 /* bus resource, from (BusBase + 1) to BusLimit */
183 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusLimit, 0x0,
184 (ri->BusLimit - ri->BusBase));
185
186 /* IO resource */
187 acpigen_resource_word(1, 0xc, 0x3, 0, ri->IoBase, ri->PciResourceIoBase - 1,
188 0x0, ri->PciResourceIoBase - ri->IoBase);
189
190 /* Mem32 resource */
191 acpigen_resource_dword(0, 0xc, 1, 0, ri->Mmio32Base,
192 ri->PciResourceMem32Base - 1, 0x0,
193 ri->PciResourceMem32Base - ri->Mmio32Base);
194
195 /* Mem64 resource */
196 acpigen_resource_qword(0, 0xc, 1, 0, ri->Mmio64Base,
197 ri->PciResourceMem64Base - 1, 0x0,
198 ri->PciResourceMem64Base - ri->Mmio64Base);
199 } else {
200 /* bus resource, from (BusBase + 1) to BusLimit */
201 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
202
203 /* IO resource */
204 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
205
206 /* Mem32 resource */
207 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
208
209 /* Mem64 resource */
210 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
211 }
212
213 acpigen_write_resourcetemplate_footer();
214}
215
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200216static void create_dsdt_dino_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri, bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800217{
218 /*
219 Stacks 8 .. B (TYPE_DINO)
220 Scope: DI<socket><stack> for DINO, ResourceTemplate: DT
221 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: MT
222 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: HT
223 */
224
225 enum {
226 DSDT_DINO = 0,
227 DSDT_CPM,
228 DSDT_HQM,
229 DSDT_CPM1,
230 DSDT_HQM1
231 };
232 uint8_t rlist[] = {DSDT_DINO, DSDT_CPM, DSDT_HQM, DSDT_CPM1, DSDT_HQM1};
233
234 for (int i = 0; i < ARRAY_SIZE(rlist); ++i) {
235 uint8_t bus_base, bus_limit;
236 uint64_t mem64_base, mem64_limit;
237 char tres[16];
238
239 /* Note, This allocates the resources in a different order than
240 * coreboot (DINO base is last). This causes the kernel to
241 * reallocate the DINO BARs.
242 * TODO: Use the resource settings from coreboot */
243 if (rlist[i] == DSDT_DINO) {
244 bus_base = ri->BusBase;
245 bus_limit = ri->BusBase;
246 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
247 + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
248 mem64_limit = ri->PciResourceMem64Limit;
249 snprintf(tres, sizeof(tres), "DT%d%X", socket, stack);
250 } else if (rlist[i] == DSDT_CPM) {
251 bus_base = ri->BusBase + CPM_BUS_OFFSET;
252 bus_limit = bus_base + CPM_RESERVED_BUS;
253 mem64_base = ri->PciResourceMem64Base;
254 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
255 snprintf(tres, sizeof(tres), "MT%d%X", socket, stack);
256 } else if (rlist[i] == DSDT_HQM) {
257 bus_base = ri->BusBase + HQM_BUS_OFFSET;
258 bus_limit = bus_base + HQM_RESERVED_BUS;
259 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE;
260 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
261 snprintf(tres, sizeof(tres), "HT%d%X", socket, stack);
262 } else if (rlist[i] == DSDT_CPM1) {
263 bus_base = ri->BusBase + CPM1_BUS_OFFSET;
264 bus_limit = bus_base + CPM_RESERVED_BUS;
265 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
266 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
267 snprintf(tres, sizeof(tres), "MU%d%X", socket, stack);
268 } else { // DSDT_HQM1
269 bus_base = ri->BusBase + HQM1_BUS_OFFSET;
270 bus_limit = bus_base + HQM_RESERVED_BUS;
271 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
272 + CPM_MMIO_SIZE;
273 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
274 snprintf(tres, sizeof(tres), "HU%d%X", socket, stack);
275 }
276
277 printk(BIOS_DEBUG,
278 "\tCreating Dino ResourceTemplate %s for socket: %d, "
279 "stack: %d\n bus_base:0x%x, bus_limit:0x%x\n",
280 tres, socket, stack, bus_base, bus_limit);
281
282 acpigen_write_name(tres);
283 acpigen_write_resourcetemplate_header();
284
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200285 if (stack_enabled) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800286 acpigen_resource_word(2, 0xc, 0, 0, bus_base, bus_limit, 0x0,
287 (bus_limit - bus_base + 1));
288
289 /* Mem32 resource */
290 if (rlist[i] == DSDT_DINO)
291 acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base,
292 ri->PciResourceMem32Limit, 0x0,
293 (ri->PciResourceMem32Limit
294 - ri->PciResourceMem32Base + 1));
295
296 /* Mem64 resource */
297 acpigen_resource_qword(0, 0xc, 1, 0, mem64_base, mem64_limit, 0,
298 (mem64_limit - mem64_base + 1));
299 } else {
300 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
301
302 /* Mem32 resource */
303 if (rlist[i] == DSDT_DINO)
304 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
305
306 /* Mem64 resource */
307 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
308 }
309
310 acpigen_write_resourcetemplate_footer();
311 }
312}
313
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200314static void create_dsdt_ubox_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri, bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800315{
316 /*
317 Stacks D .. E (TYPE_UBOX)
318 Scope: UC/UD<socket><0..1> for UBOX[1-2], ResourceTemplate: UT/UU
319 */
320
321 for (int i = 0; i < 2; ++i) {
322 char tres[16];
323 /* write ResourceTemplate resource name */
324 if (i == 0)
325 snprintf(tres, sizeof(tres), "UT%d%X", socket, stack);
326 else
327 snprintf(tres, sizeof(tres), "UU%d%X", socket, stack);
328
329 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n",
330 tres, socket, stack);
331
332 acpigen_write_name(tres);
333 acpigen_write_resourcetemplate_header();
334
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200335 if (!stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800336 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
337 else if (i == 0)
338 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
339 else
340 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusBase + 1,
341 0x0, 1);
342
343 acpigen_write_resourcetemplate_footer();
344 }
345}
346
347
348/*
349 * Add a DSDT ACPI Name field for STACK enable setting.
350 * This is retrieved by the device _STA defined in iiostack.asl
351 */
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200352static void create_dsdt_stack_sta(uint8_t socket, uint8_t stack, const STACK_RES *ri, bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800353{
354 char stack_sta[16];
355 snprintf(stack_sta, sizeof(stack_sta), "ST%d%X", socket, stack);
356
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200357 if (!stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800358 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_OFF);
359 else
360 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_ON);
361}
362
363void uncore_inject_dsdt(const struct device *device)
364{
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200365 bool stack_enabled;
366
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800367 /* Only add RTxx entries once. */
368 if (device->bus->secondary != 0)
369 return;
370
371 /*
372 Write stack scope - this needs to match RP ACPI scopes.
373 Stacks 0 (TYPE_UBOX_IIO)
374 Scope: PC<socket><stack>, ResourceTemplate: P0RS
375 Stacks 1 .. 5 (TYPE_UBOX_IIO)
376 Scope: PC<socket><stack> & CX<socket><stack>, ResourceTemplate: RBRS
377 Stacks 8 .. B (TYPE_DINO)
378 Scope: DI<socket><stack> for DINO, ResourceTemplate: RBRS
379 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: RBRS
380 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: RBRS
381 Stacks D .. E (TYPE_UBOX)
382 Scope: UC<socket><0..1> for UBOX[1-2], ResourceTemplate: UNRS
383 */
384
385 printk(BIOS_DEBUG, "%s device: %s\n", __func__, dev_path(device));
386
387 acpigen_write_scope("\\_SB");
388
389 /* The _CSR generation must match SPR iiostack.asl. */
390 const IIO_UDS *hob = get_iio_uds();
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200391 /* Iterate over CONFIG_MAX_SOCKET to keep ASL templates and DSDT injection in sync */
392 for (uint8_t socket = 0; socket < CONFIG_MAX_SOCKET; ++socket) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800393 for (int stack = 0; stack < MAX_LOGIC_IIO_STACK; ++stack) {
394 const STACK_RES *ri =
395 &hob->PlatformData.IIO_resource[socket].StackRes[stack];
396
Patrick Rudolphb096d622023-07-14 17:18:18 +0200397 stack_enabled = soc_cpu_is_enabled(socket) &&
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200398 ri->Personality < TYPE_RESERVED;
399
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800400 printk(BIOS_DEBUG, "%s processing socket: %d, stack: %d, type: %d\n",
401 __func__, socket, stack, ri->Personality);
402
403 if (stack <= IioStack5) { // TYPE_UBOX_IIO
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200404 create_dsdt_iou_pci_resource(socket, stack, ri, stack_enabled);
405 create_dsdt_iou_cxl_resource(socket, stack, ri, stack_enabled);
406 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800407 } else if (stack >= IioStack8 && stack <= IioStack11) { // TYPE_DINO
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200408 create_dsdt_dino_resource(socket, stack, ri, stack_enabled);
409 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800410 } else if (stack == IioStack13) { // TYPE_UBOX
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200411 create_dsdt_ubox_resource(socket, stack, ri, stack_enabled);
412 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800413 }
414 }
415 }
416
417 acpigen_pop_len();
418}
419
420/* TODO: See if we can use the common generate_p_state_entries */
421void soc_power_states_generation(int core, int cores_per_package)
422{
423 int ratio_min, ratio_max, ratio_turbo, ratio_step;
424 int coord_type, power_max, power_unit, num_entries;
425 int ratio, power, clock, clock_max;
426 msr_t msr;
427
428 /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
429 msr = rdmsr(MSR_MISC_PWR_MGMT);
430 if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
431 coord_type = SW_ANY;
432 else
433 coord_type = HW_ALL;
434
435 /* Get bus ratio limits and calculate clock speeds */
436 msr = rdmsr(MSR_PLATFORM_INFO);
437 ratio_min = (msr.hi >> (40 - 32)) & 0xff; /* Max Efficiency Ratio */
438
439 /* Determine if this CPU has configurable TDP */
440 if (cpu_config_tdp_levels()) {
441 /* Set max ratio to nominal TDP ratio */
442 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
443 ratio_max = msr.lo & 0xff;
444 } else {
445 /* Max Non-Turbo Ratio */
446 ratio_max = (msr.lo >> 8) & 0xff;
447 }
448 clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ;
449
450 /* Calculate CPU TDP in mW */
451 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
452 power_unit = 2 << ((msr.lo & 0xf) - 1);
453 msr = rdmsr(MSR_PKG_POWER_SKU);
454 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
455
456 /* Write _PCT indicating use of FFixedHW */
457 acpigen_write_empty_PCT();
458
459 /* Write _PPC with no limit on supported P-state */
460 acpigen_write_PPC_NVS();
461
462 /* Write PSD indicating configured coordination type */
463 acpigen_write_PSD_package(core, 1, coord_type);
464
465 /* Add P-state entries in _PSS table */
466 acpigen_write_name("_PSS");
467
468 /* Determine ratio points */
469 ratio_step = PSS_RATIO_STEP;
470 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
471 if (num_entries > PSS_MAX_ENTRIES) {
472 ratio_step += 1;
473 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
474 }
475
476 /* P[T] is Turbo state if enabled */
477 if (get_turbo_state() == TURBO_ENABLED) {
478 /* _PSS package count including Turbo */
479 acpigen_write_package(num_entries + 2);
480
481 msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
482 ratio_turbo = msr.lo & 0xff;
483
484 /* Add entry for Turbo ratio */
485 acpigen_write_PSS_package(clock_max + 1, /* MHz */
486 power_max, /* mW */
487 PSS_LATENCY_TRANSITION, /* lat1 */
488 PSS_LATENCY_BUSMASTER, /* lat2 */
489 ratio_turbo << 8, /* control */
490 ratio_turbo << 8); /* status */
491 } else {
492 /* _PSS package count without Turbo */
493 acpigen_write_package(num_entries + 1);
494 }
495
496 /* First regular entry is max non-turbo ratio */
497 acpigen_write_PSS_package(clock_max, /* MHz */
498 power_max, /* mW */
499 PSS_LATENCY_TRANSITION, /* lat1 */
500 PSS_LATENCY_BUSMASTER, /* lat2 */
501 ratio_max << 8, /* control */
502 ratio_max << 8); /* status */
503
504 /* Generate the remaining entries */
505 for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min;
506 ratio -= ratio_step) {
507
508 /* Calculate power at this ratio */
509 power = common_calculate_power_ratio(power_max, ratio_max, ratio);
510 clock = ratio * CONFIG_CPU_BCLK_MHZ;
511 // clock = 1;
512 acpigen_write_PSS_package(clock, /* MHz */
513 power, /* mW */
514 PSS_LATENCY_TRANSITION, /* lat1 */
515 PSS_LATENCY_BUSMASTER, /* lat2 */
516 ratio << 8, /* control */
517 ratio << 8); /* status */
518 }
519
520 /* Fix package length */
521 acpigen_pop_len();
522}
523
524unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current)
525{
526 struct device *cpu;
527 uint8_t num_cpus = 0;
528
529 for (cpu = all_devices; cpu; cpu = cpu->next) {
530 if ((cpu->path.type != DEVICE_PATH_APIC)
531 || (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
532 continue;
533 }
534 if (!cpu->enabled)
535 continue;
Kyösti Mälkki2e9f0d32023-04-07 23:05:46 +0300536 current = acpi_create_madt_one_lapic(current, num_cpus, cpu->path.apic.apic_id);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800537 num_cpus++;
538 }
539
540 return current;
541}
542
543unsigned long acpi_fill_cedt(unsigned long current)
544{
545 const IIO_UDS *hob = get_iio_uds();
546 union uid {
547 uint32_t data;
548 struct {
549 uint8_t byte0;
550 uint8_t byte1;
551 uint8_t byte2;
552 uint8_t byte3;
553 };
554 } cxl_uid;
555 u32 cxl_ver;
556 u64 base;
557
558 cxl_uid.byte0 = 'C';
559 cxl_uid.byte1 = 'X';
560 /* Loop through all sockets and stacks, add CHBS for each CXL IIO stack */
Patrick Rudolphac028572023-07-14 17:44:33 +0200561 for (uint8_t socket = 0, iio = 0; iio < hob->PlatformData.numofIIO; ++socket) {
562 if (!soc_cpu_is_enabled(socket))
563 continue;
564 iio++;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800565 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
Patrick Rudolphac028572023-07-14 17:44:33 +0200566 const STACK_RES *ri;
567 ri = &hob->PlatformData.IIO_resource[socket].StackRes[x];
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800568 if (!is_iio_cxl_stack_res(ri))
569 continue;
570 /* uid needs to match with ACPI CXL device ID, eg. acpi/iiostack.asl */
Patrick Rudolphac028572023-07-14 17:44:33 +0200571 cxl_uid.byte2 = socket + '0';
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800572 cxl_uid.byte3 = x + '0';
573 cxl_ver = ACPI_CEDT_CHBS_CXL_VER_1_1;
574 base = ri->Mmio32Base; /* DP RCRB base */
575 current += acpi_create_cedt_chbs((acpi_cedt_chbs_t *)current,
576 cxl_uid.data, cxl_ver, base);
577 }
578 }
579
580 return current;
581}