blob: d9d82ac3aafac0c62fe2073a7113faef264530cb [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;
50 fadt->gpe0_blk = pmbase + 0x60;
51 fadt->p_lvl2_lat = ACPI_FADT_C2_NOT_SUPPORTED;
52 fadt->p_lvl3_lat = ACPI_FADT_C3_NOT_SUPPORTED;
53 fadt->duty_offset = 1;
54
55 fadt->x_pm1b_evt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
56 fadt->x_pm1b_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
57
58 /* PM2 Control Registers */
59 fadt->x_pm2_cnt_blk.space_id = ACPI_ADDRESS_SPACE_IO;
60 fadt->x_pm2_cnt_blk.bit_width = fadt->pm2_cnt_len * 8;
61 fadt->x_pm2_cnt_blk.bit_offset = 0;
62 fadt->x_pm2_cnt_blk.access_size = ACPI_ACCESS_SIZE_UNDEFINED;
63 fadt->x_pm2_cnt_blk.addrl = pmbase + PM2_CNT;
64 fadt->x_pm2_cnt_blk.addrh = 0x0;
65
66 /* PM1 Timer Register */
67 fadt->x_pm_tmr_blk.space_id = ACPI_ADDRESS_SPACE_IO;
68 fadt->x_pm_tmr_blk.bit_width = fadt->pm_tmr_len * 8;
69 fadt->x_pm_tmr_blk.bit_offset = 0;
70 fadt->x_pm_tmr_blk.access_size = ACPI_ACCESS_SIZE_DWORD_ACCESS;
71 fadt->x_pm_tmr_blk.addrl = pmbase + PM1_TMR;
72 fadt->x_pm_tmr_blk.addrh = 0x0;
73
74 fadt->x_gpe0_blk.space_id = ACPI_ADDRESS_SPACE_IO;
75 fadt->x_gpe0_blk.bit_width = fadt->gpe0_blk_len * 8;
76 fadt->x_gpe0_blk.bit_offset = 0;
77 fadt->x_gpe0_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
78 fadt->x_gpe0_blk.addrl = fadt->gpe0_blk;
79 fadt->x_gpe0_blk.addrh = 0x0;
80
81 fadt->x_gpe1_blk.space_id = ACPI_ADDRESS_SPACE_IO;
82 fadt->x_gpe1_blk.bit_width = fadt->gpe1_blk_len * 8;
83 fadt->x_gpe1_blk.bit_offset = 0;
84 fadt->x_gpe1_blk.access_size = ACPI_ACCESS_SIZE_BYTE_ACCESS;
85 fadt->x_gpe1_blk.addrl = fadt->gpe1_blk;
86 fadt->x_gpe1_blk.addrh = 0x0;
87}
88
89static void create_dsdt_iou_pci_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri)
90{
91 /*
92 Stacks 0 (TYPE_UBOX_IIO)
93 Scope: PC<socket><stack>, ResourceTemplate: P0RS
94 Stacks 1 .. 5 (TYPE_UBOX_IIO)
95 Scope: PC<socket><stack>, ResourceTemplate: RBRS
96 */
97
98 /* Write ResourceTemplate resource name */
99 char tres[16];
100 snprintf(tres, sizeof(tres), "PT%d%X", socket, stack);
101 acpigen_write_name(tres);
102
103 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
104 socket, stack);
105
106 acpigen_write_resourcetemplate_header();
107
108 /*
109 * ACPI spec requires that each bus device (stack) has a valid
110 * resource template. Disabled devices still need a valid _CRS
111 * although the values are ignored. The FWTS sanity check does
112 * not pass when using the HOB stack resources to generate the
113 * _CRS resource template for disabled stacks, so we provide a
114 * zeroed resource template to satisfy both the spec and FWTS.
115 */
116 const bool stack_enabled = ri->Personality < TYPE_RESERVED;
117
118 /* Bus Resource */
119 if (stack_enabled) {
120 /* For stack with CXL device, the PCIe bus resource is BusBase only. */
121 if (is_iio_cxl_stack_res(ri))
122 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
123 else
124 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusLimit, 0x0,
125 (ri->BusLimit - ri->BusBase + 1));
126 } else {
127 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
128 }
129
130 /* Additional IO resources on socket 0 bus 0 */
131 if (socket == 0 && stack == 0) {
132 /* ACPI 6.4.2.5 I/O Port Descriptor */
133 acpigen_write_io16(0xCF8, 0xCFF, 0x1, 0x8, 1);
134
135 /* IO decode CF8-CFF */
136 acpigen_resource_word(1, 0xc, 0x3, 0, 0x0000, 0x03AF, 0, 0x03B0);
137 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03E0, 0x0CF7, 0, 0x0918);
138 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03B0, 0x03BB, 0, 0x000C);
139 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03C0, 0x03DF, 0, 0x0020);
140 }
141
142 /* IO resource */
143 if (stack_enabled) {
144 acpigen_resource_word(1, 0xc, 0x3, 0, ri->PciResourceIoBase,
145 ri->PciResourceIoLimit, 0x0,
146 (ri->PciResourceIoLimit - ri->PciResourceIoBase + 1));
147
148 /* Additional Mem32 resources on socket 0 bus 0 */
149 if (socket == 0 && stack == 0) {
150 acpigen_resource_dword(0, 0xc, 3, 0, VGA_BASE_ADDRESS,
151 (VGA_BASE_ADDRESS + VGA_BASE_SIZE - 1), 0x0,
152 VGA_BASE_SIZE);
153 acpigen_resource_dword(0, 0xc, 1, 0, SPI_BASE_ADDRESS,
154 (SPI_BASE_ADDRESS + SPI_BASE_SIZE - 1), 0x0,
155 SPI_BASE_SIZE);
156 }
157
158 /* Mem32 resource */
159 acpigen_resource_dword(
160 0, 0xc, 1, 0, ri->PciResourceMem32Base, ri->PciResourceMem32Limit, 0x0,
161 (ri->PciResourceMem32Limit - ri->PciResourceMem32Base + 1));
162
163 /* Mem64 resource */
164 acpigen_resource_qword(
165 0, 0xc, 1, 0, ri->PciResourceMem64Base, ri->PciResourceMem64Limit, 0x0,
166 (ri->PciResourceMem64Limit - ri->PciResourceMem64Base + 1));
167 } else {
168 /* Zeroed IO resource */
169 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
170
171 /* Zeroed Mem32 resource */
172 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
173
174 /* Zeroed Mem64 resource */
175 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
176 }
177
178 acpigen_write_resourcetemplate_footer();
179}
180
181static void create_dsdt_iou_cxl_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri)
182{
183 /*
184 Stacks 1 .. 5 (TYPE_UBOX_IIO)
185 Scope: CX<socket><stack>, ResourceTemplate: RBRS
186 */
187 /* write ResourceTemplate resource name */
188 char tres[16];
189 snprintf(tres, sizeof(tres), "CT%d%X", socket, stack);
190 acpigen_write_name(tres);
191
192 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
193 socket, stack);
194
195 acpigen_write_resourcetemplate_header();
196
197 if (ri->Personality < TYPE_RESERVED) {
198 /* bus resource, from (BusBase + 1) to BusLimit */
199 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusLimit, 0x0,
200 (ri->BusLimit - ri->BusBase));
201
202 /* IO resource */
203 acpigen_resource_word(1, 0xc, 0x3, 0, ri->IoBase, ri->PciResourceIoBase - 1,
204 0x0, ri->PciResourceIoBase - ri->IoBase);
205
206 /* Mem32 resource */
207 acpigen_resource_dword(0, 0xc, 1, 0, ri->Mmio32Base,
208 ri->PciResourceMem32Base - 1, 0x0,
209 ri->PciResourceMem32Base - ri->Mmio32Base);
210
211 /* Mem64 resource */
212 acpigen_resource_qword(0, 0xc, 1, 0, ri->Mmio64Base,
213 ri->PciResourceMem64Base - 1, 0x0,
214 ri->PciResourceMem64Base - ri->Mmio64Base);
215 } else {
216 /* bus resource, from (BusBase + 1) to BusLimit */
217 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
218
219 /* IO resource */
220 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
221
222 /* Mem32 resource */
223 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
224
225 /* Mem64 resource */
226 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
227 }
228
229 acpigen_write_resourcetemplate_footer();
230}
231
232static void create_dsdt_dino_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri)
233{
234 /*
235 Stacks 8 .. B (TYPE_DINO)
236 Scope: DI<socket><stack> for DINO, ResourceTemplate: DT
237 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: MT
238 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: HT
239 */
240
241 enum {
242 DSDT_DINO = 0,
243 DSDT_CPM,
244 DSDT_HQM,
245 DSDT_CPM1,
246 DSDT_HQM1
247 };
248 uint8_t rlist[] = {DSDT_DINO, DSDT_CPM, DSDT_HQM, DSDT_CPM1, DSDT_HQM1};
249
250 for (int i = 0; i < ARRAY_SIZE(rlist); ++i) {
251 uint8_t bus_base, bus_limit;
252 uint64_t mem64_base, mem64_limit;
253 char tres[16];
254
255 /* Note, This allocates the resources in a different order than
256 * coreboot (DINO base is last). This causes the kernel to
257 * reallocate the DINO BARs.
258 * TODO: Use the resource settings from coreboot */
259 if (rlist[i] == DSDT_DINO) {
260 bus_base = ri->BusBase;
261 bus_limit = ri->BusBase;
262 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
263 + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
264 mem64_limit = ri->PciResourceMem64Limit;
265 snprintf(tres, sizeof(tres), "DT%d%X", socket, stack);
266 } else if (rlist[i] == DSDT_CPM) {
267 bus_base = ri->BusBase + CPM_BUS_OFFSET;
268 bus_limit = bus_base + CPM_RESERVED_BUS;
269 mem64_base = ri->PciResourceMem64Base;
270 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
271 snprintf(tres, sizeof(tres), "MT%d%X", socket, stack);
272 } else if (rlist[i] == DSDT_HQM) {
273 bus_base = ri->BusBase + HQM_BUS_OFFSET;
274 bus_limit = bus_base + HQM_RESERVED_BUS;
275 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE;
276 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
277 snprintf(tres, sizeof(tres), "HT%d%X", socket, stack);
278 } else if (rlist[i] == DSDT_CPM1) {
279 bus_base = ri->BusBase + CPM1_BUS_OFFSET;
280 bus_limit = bus_base + CPM_RESERVED_BUS;
281 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
282 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
283 snprintf(tres, sizeof(tres), "MU%d%X", socket, stack);
284 } else { // DSDT_HQM1
285 bus_base = ri->BusBase + HQM1_BUS_OFFSET;
286 bus_limit = bus_base + HQM_RESERVED_BUS;
287 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
288 + CPM_MMIO_SIZE;
289 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
290 snprintf(tres, sizeof(tres), "HU%d%X", socket, stack);
291 }
292
293 printk(BIOS_DEBUG,
294 "\tCreating Dino ResourceTemplate %s for socket: %d, "
295 "stack: %d\n bus_base:0x%x, bus_limit:0x%x\n",
296 tres, socket, stack, bus_base, bus_limit);
297
298 acpigen_write_name(tres);
299 acpigen_write_resourcetemplate_header();
300
301 if (ri->Personality < TYPE_RESERVED) {
302 acpigen_resource_word(2, 0xc, 0, 0, bus_base, bus_limit, 0x0,
303 (bus_limit - bus_base + 1));
304
305 /* Mem32 resource */
306 if (rlist[i] == DSDT_DINO)
307 acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base,
308 ri->PciResourceMem32Limit, 0x0,
309 (ri->PciResourceMem32Limit
310 - ri->PciResourceMem32Base + 1));
311
312 /* Mem64 resource */
313 acpigen_resource_qword(0, 0xc, 1, 0, mem64_base, mem64_limit, 0,
314 (mem64_limit - mem64_base + 1));
315 } else {
316 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
317
318 /* Mem32 resource */
319 if (rlist[i] == DSDT_DINO)
320 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
321
322 /* Mem64 resource */
323 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
324 }
325
326 acpigen_write_resourcetemplate_footer();
327 }
328}
329
330static void create_dsdt_ubox_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri)
331{
332 /*
333 Stacks D .. E (TYPE_UBOX)
334 Scope: UC/UD<socket><0..1> for UBOX[1-2], ResourceTemplate: UT/UU
335 */
336
337 for (int i = 0; i < 2; ++i) {
338 char tres[16];
339 /* write ResourceTemplate resource name */
340 if (i == 0)
341 snprintf(tres, sizeof(tres), "UT%d%X", socket, stack);
342 else
343 snprintf(tres, sizeof(tres), "UU%d%X", socket, stack);
344
345 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n",
346 tres, socket, stack);
347
348 acpigen_write_name(tres);
349 acpigen_write_resourcetemplate_header();
350
351 if (ri->Personality >= TYPE_RESERVED)
352 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
353 else if (i == 0)
354 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
355 else
356 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusBase + 1,
357 0x0, 1);
358
359 acpigen_write_resourcetemplate_footer();
360 }
361}
362
363
364/*
365 * Add a DSDT ACPI Name field for STACK enable setting.
366 * This is retrieved by the device _STA defined in iiostack.asl
367 */
368static void create_dsdt_stack_sta(uint8_t socket, uint8_t stack, const STACK_RES *ri)
369{
370 char stack_sta[16];
371 snprintf(stack_sta, sizeof(stack_sta), "ST%d%X", socket, stack);
372
373 if (ri->Personality >= TYPE_RESERVED)
374 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_OFF);
375 else
376 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_ON);
377}
378
379void uncore_inject_dsdt(const struct device *device)
380{
381 /* Only add RTxx entries once. */
382 if (device->bus->secondary != 0)
383 return;
384
385 /*
386 Write stack scope - this needs to match RP ACPI scopes.
387 Stacks 0 (TYPE_UBOX_IIO)
388 Scope: PC<socket><stack>, ResourceTemplate: P0RS
389 Stacks 1 .. 5 (TYPE_UBOX_IIO)
390 Scope: PC<socket><stack> & CX<socket><stack>, ResourceTemplate: RBRS
391 Stacks 8 .. B (TYPE_DINO)
392 Scope: DI<socket><stack> for DINO, ResourceTemplate: RBRS
393 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: RBRS
394 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: RBRS
395 Stacks D .. E (TYPE_UBOX)
396 Scope: UC<socket><0..1> for UBOX[1-2], ResourceTemplate: UNRS
397 */
398
399 printk(BIOS_DEBUG, "%s device: %s\n", __func__, dev_path(device));
400
401 acpigen_write_scope("\\_SB");
402
403 /* The _CSR generation must match SPR iiostack.asl. */
404 const IIO_UDS *hob = get_iio_uds();
405 /* TODO: DSDT uses CONFIG_MAX_SOCKET while PlatformData.numofIIO is the actual number
406 of CPUs plugged in, although it doesn't cause serious errors when not all CPUs are
407 plugged in, they should be in sync. */
408 for (uint8_t socket = 0; socket < hob->PlatformData.numofIIO; ++socket) {
409 for (int stack = 0; stack < MAX_LOGIC_IIO_STACK; ++stack) {
410 const STACK_RES *ri =
411 &hob->PlatformData.IIO_resource[socket].StackRes[stack];
412
413 printk(BIOS_DEBUG, "%s processing socket: %d, stack: %d, type: %d\n",
414 __func__, socket, stack, ri->Personality);
415
416 if (stack <= IioStack5) { // TYPE_UBOX_IIO
417 create_dsdt_iou_pci_resource(socket, stack, ri);
418 create_dsdt_iou_cxl_resource(socket, stack, ri);
419 create_dsdt_stack_sta(socket, stack, ri);
420 } else if (stack >= IioStack8 && stack <= IioStack11) { // TYPE_DINO
421 create_dsdt_dino_resource(socket, stack, ri);
422 create_dsdt_stack_sta(socket, stack, ri);
423 } else if (stack == IioStack13) { // TYPE_UBOX
424 create_dsdt_ubox_resource(socket, stack, ri);
425 create_dsdt_stack_sta(socket, stack, ri);
426 }
427 }
428 }
429
430 acpigen_pop_len();
431}
432
433/* TODO: See if we can use the common generate_p_state_entries */
434void soc_power_states_generation(int core, int cores_per_package)
435{
436 int ratio_min, ratio_max, ratio_turbo, ratio_step;
437 int coord_type, power_max, power_unit, num_entries;
438 int ratio, power, clock, clock_max;
439 msr_t msr;
440
441 /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
442 msr = rdmsr(MSR_MISC_PWR_MGMT);
443 if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
444 coord_type = SW_ANY;
445 else
446 coord_type = HW_ALL;
447
448 /* Get bus ratio limits and calculate clock speeds */
449 msr = rdmsr(MSR_PLATFORM_INFO);
450 ratio_min = (msr.hi >> (40 - 32)) & 0xff; /* Max Efficiency Ratio */
451
452 /* Determine if this CPU has configurable TDP */
453 if (cpu_config_tdp_levels()) {
454 /* Set max ratio to nominal TDP ratio */
455 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
456 ratio_max = msr.lo & 0xff;
457 } else {
458 /* Max Non-Turbo Ratio */
459 ratio_max = (msr.lo >> 8) & 0xff;
460 }
461 clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ;
462
463 /* Calculate CPU TDP in mW */
464 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
465 power_unit = 2 << ((msr.lo & 0xf) - 1);
466 msr = rdmsr(MSR_PKG_POWER_SKU);
467 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
468
469 /* Write _PCT indicating use of FFixedHW */
470 acpigen_write_empty_PCT();
471
472 /* Write _PPC with no limit on supported P-state */
473 acpigen_write_PPC_NVS();
474
475 /* Write PSD indicating configured coordination type */
476 acpigen_write_PSD_package(core, 1, coord_type);
477
478 /* Add P-state entries in _PSS table */
479 acpigen_write_name("_PSS");
480
481 /* Determine ratio points */
482 ratio_step = PSS_RATIO_STEP;
483 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
484 if (num_entries > PSS_MAX_ENTRIES) {
485 ratio_step += 1;
486 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
487 }
488
489 /* P[T] is Turbo state if enabled */
490 if (get_turbo_state() == TURBO_ENABLED) {
491 /* _PSS package count including Turbo */
492 acpigen_write_package(num_entries + 2);
493
494 msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
495 ratio_turbo = msr.lo & 0xff;
496
497 /* Add entry for Turbo ratio */
498 acpigen_write_PSS_package(clock_max + 1, /* MHz */
499 power_max, /* mW */
500 PSS_LATENCY_TRANSITION, /* lat1 */
501 PSS_LATENCY_BUSMASTER, /* lat2 */
502 ratio_turbo << 8, /* control */
503 ratio_turbo << 8); /* status */
504 } else {
505 /* _PSS package count without Turbo */
506 acpigen_write_package(num_entries + 1);
507 }
508
509 /* First regular entry is max non-turbo ratio */
510 acpigen_write_PSS_package(clock_max, /* MHz */
511 power_max, /* mW */
512 PSS_LATENCY_TRANSITION, /* lat1 */
513 PSS_LATENCY_BUSMASTER, /* lat2 */
514 ratio_max << 8, /* control */
515 ratio_max << 8); /* status */
516
517 /* Generate the remaining entries */
518 for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min;
519 ratio -= ratio_step) {
520
521 /* Calculate power at this ratio */
522 power = common_calculate_power_ratio(power_max, ratio_max, ratio);
523 clock = ratio * CONFIG_CPU_BCLK_MHZ;
524 // clock = 1;
525 acpigen_write_PSS_package(clock, /* MHz */
526 power, /* mW */
527 PSS_LATENCY_TRANSITION, /* lat1 */
528 PSS_LATENCY_BUSMASTER, /* lat2 */
529 ratio << 8, /* control */
530 ratio << 8); /* status */
531 }
532
533 /* Fix package length */
534 acpigen_pop_len();
535}
536
537unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current)
538{
539 struct device *cpu;
540 uint8_t num_cpus = 0;
541
542 for (cpu = all_devices; cpu; cpu = cpu->next) {
543 if ((cpu->path.type != DEVICE_PATH_APIC)
544 || (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
545 continue;
546 }
547 if (!cpu->enabled)
548 continue;
549 current += acpi_create_madt_lapic((acpi_madt_lapic_t *)current, num_cpus,
550 cpu->path.apic.apic_id);
551 num_cpus++;
552 }
553
554 return current;
555}
556
557unsigned long acpi_fill_cedt(unsigned long current)
558{
559 const IIO_UDS *hob = get_iio_uds();
560 union uid {
561 uint32_t data;
562 struct {
563 uint8_t byte0;
564 uint8_t byte1;
565 uint8_t byte2;
566 uint8_t byte3;
567 };
568 } cxl_uid;
569 u32 cxl_ver;
570 u64 base;
571
572 cxl_uid.byte0 = 'C';
573 cxl_uid.byte1 = 'X';
574 /* Loop through all sockets and stacks, add CHBS for each CXL IIO stack */
575 for (uint8_t s = 0; s < hob->PlatformData.numofIIO; ++s) {
576 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
577 const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
578 if (!is_iio_cxl_stack_res(ri))
579 continue;
580 /* uid needs to match with ACPI CXL device ID, eg. acpi/iiostack.asl */
581 cxl_uid.byte2 = s + '0';
582 cxl_uid.byte3 = x + '0';
583 cxl_ver = ACPI_CEDT_CHBS_CXL_VER_1_1;
584 base = ri->Mmio32Base; /* DP RCRB base */
585 current += acpi_create_cedt_chbs((acpi_cedt_chbs_t *)current,
586 cxl_uid.data, cxl_ver, base);
587 }
588 }
589
590 return current;
591}