blob: e7ce5e37739f322a9e6b70573825e717da9aa7ff [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
Patrick Rudolph6e6832d2023-04-04 09:37:30 +020056static void create_dsdt_iou_pci_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri,
57 bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080058{
59 /*
60 Stacks 0 (TYPE_UBOX_IIO)
61 Scope: PC<socket><stack>, ResourceTemplate: P0RS
62 Stacks 1 .. 5 (TYPE_UBOX_IIO)
63 Scope: PC<socket><stack>, ResourceTemplate: RBRS
64 */
65
66 /* Write ResourceTemplate resource name */
67 char tres[16];
68 snprintf(tres, sizeof(tres), "PT%d%X", socket, stack);
69 acpigen_write_name(tres);
70
71 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
72 socket, stack);
73
74 acpigen_write_resourcetemplate_header();
75
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080076 /* Bus Resource */
77 if (stack_enabled) {
78 /* For stack with CXL device, the PCIe bus resource is BusBase only. */
79 if (is_iio_cxl_stack_res(ri))
80 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
81 else
82 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusLimit, 0x0,
83 (ri->BusLimit - ri->BusBase + 1));
84 } else {
85 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
86 }
87
88 /* Additional IO resources on socket 0 bus 0 */
89 if (socket == 0 && stack == 0) {
90 /* ACPI 6.4.2.5 I/O Port Descriptor */
91 acpigen_write_io16(0xCF8, 0xCFF, 0x1, 0x8, 1);
92
93 /* IO decode CF8-CFF */
94 acpigen_resource_word(1, 0xc, 0x3, 0, 0x0000, 0x03AF, 0, 0x03B0);
95 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03E0, 0x0CF7, 0, 0x0918);
96 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03B0, 0x03BB, 0, 0x000C);
97 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03C0, 0x03DF, 0, 0x0020);
98 }
99
100 /* IO resource */
101 if (stack_enabled) {
102 acpigen_resource_word(1, 0xc, 0x3, 0, ri->PciResourceIoBase,
103 ri->PciResourceIoLimit, 0x0,
104 (ri->PciResourceIoLimit - ri->PciResourceIoBase + 1));
105
106 /* Additional Mem32 resources on socket 0 bus 0 */
107 if (socket == 0 && stack == 0) {
Felix Held97439ec2023-06-05 19:30:23 +0200108 acpigen_resource_dword(0, 0xc, 3, 0, VGA_MMIO_BASE,
109 VGA_MMIO_LIMIT, 0x0, VGA_MMIO_SIZE);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800110 acpigen_resource_dword(0, 0xc, 1, 0, SPI_BASE_ADDRESS,
111 (SPI_BASE_ADDRESS + SPI_BASE_SIZE - 1), 0x0,
112 SPI_BASE_SIZE);
113 }
114
115 /* Mem32 resource */
116 acpigen_resource_dword(
117 0, 0xc, 1, 0, ri->PciResourceMem32Base, ri->PciResourceMem32Limit, 0x0,
118 (ri->PciResourceMem32Limit - ri->PciResourceMem32Base + 1));
119
120 /* Mem64 resource */
121 acpigen_resource_qword(
122 0, 0xc, 1, 0, ri->PciResourceMem64Base, ri->PciResourceMem64Limit, 0x0,
123 (ri->PciResourceMem64Limit - ri->PciResourceMem64Base + 1));
124 } else {
125 /* Zeroed IO resource */
126 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
127
128 /* Zeroed Mem32 resource */
129 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
130
131 /* Zeroed Mem64 resource */
132 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
133 }
134
135 acpigen_write_resourcetemplate_footer();
136}
137
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200138static 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 -0800139{
140 /*
141 Stacks 1 .. 5 (TYPE_UBOX_IIO)
142 Scope: CX<socket><stack>, ResourceTemplate: RBRS
143 */
144 /* write ResourceTemplate resource name */
145 char tres[16];
146 snprintf(tres, sizeof(tres), "CT%d%X", socket, stack);
147 acpigen_write_name(tres);
148
149 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
150 socket, stack);
151
152 acpigen_write_resourcetemplate_header();
153
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200154 if (stack_enabled) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800155 /* bus resource, from (BusBase + 1) to BusLimit */
156 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusLimit, 0x0,
157 (ri->BusLimit - ri->BusBase));
158
159 /* IO resource */
160 acpigen_resource_word(1, 0xc, 0x3, 0, ri->IoBase, ri->PciResourceIoBase - 1,
161 0x0, ri->PciResourceIoBase - ri->IoBase);
162
163 /* Mem32 resource */
164 acpigen_resource_dword(0, 0xc, 1, 0, ri->Mmio32Base,
165 ri->PciResourceMem32Base - 1, 0x0,
166 ri->PciResourceMem32Base - ri->Mmio32Base);
167
168 /* Mem64 resource */
169 acpigen_resource_qword(0, 0xc, 1, 0, ri->Mmio64Base,
170 ri->PciResourceMem64Base - 1, 0x0,
171 ri->PciResourceMem64Base - ri->Mmio64Base);
172 } else {
173 /* bus resource, from (BusBase + 1) to BusLimit */
174 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
175
176 /* IO resource */
177 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
178
179 /* Mem32 resource */
180 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
181
182 /* Mem64 resource */
183 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
184 }
185
186 acpigen_write_resourcetemplate_footer();
187}
188
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200189static 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 -0800190{
Arthur Heymans550f55e2022-08-24 14:44:26 +0200191 if (!stack_enabled)
192 return;
193
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800194 /*
195 Stacks 8 .. B (TYPE_DINO)
196 Scope: DI<socket><stack> for DINO, ResourceTemplate: DT
197 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: MT
198 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: HT
199 */
200
201 enum {
202 DSDT_DINO = 0,
203 DSDT_CPM,
204 DSDT_HQM,
205 DSDT_CPM1,
206 DSDT_HQM1
207 };
208 uint8_t rlist[] = {DSDT_DINO, DSDT_CPM, DSDT_HQM, DSDT_CPM1, DSDT_HQM1};
209
210 for (int i = 0; i < ARRAY_SIZE(rlist); ++i) {
211 uint8_t bus_base, bus_limit;
212 uint64_t mem64_base, mem64_limit;
213 char tres[16];
214
215 /* Note, This allocates the resources in a different order than
216 * coreboot (DINO base is last). This causes the kernel to
217 * reallocate the DINO BARs.
218 * TODO: Use the resource settings from coreboot */
219 if (rlist[i] == DSDT_DINO) {
220 bus_base = ri->BusBase;
221 bus_limit = ri->BusBase;
222 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
223 + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
224 mem64_limit = ri->PciResourceMem64Limit;
225 snprintf(tres, sizeof(tres), "DT%d%X", socket, stack);
226 } else if (rlist[i] == DSDT_CPM) {
227 bus_base = ri->BusBase + CPM_BUS_OFFSET;
228 bus_limit = bus_base + CPM_RESERVED_BUS;
229 mem64_base = ri->PciResourceMem64Base;
230 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
231 snprintf(tres, sizeof(tres), "MT%d%X", socket, stack);
232 } else if (rlist[i] == DSDT_HQM) {
233 bus_base = ri->BusBase + HQM_BUS_OFFSET;
234 bus_limit = bus_base + HQM_RESERVED_BUS;
235 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE;
236 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
237 snprintf(tres, sizeof(tres), "HT%d%X", socket, stack);
238 } else if (rlist[i] == DSDT_CPM1) {
239 bus_base = ri->BusBase + CPM1_BUS_OFFSET;
240 bus_limit = bus_base + CPM_RESERVED_BUS;
241 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
242 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
243 snprintf(tres, sizeof(tres), "MU%d%X", socket, stack);
244 } else { // DSDT_HQM1
245 bus_base = ri->BusBase + HQM1_BUS_OFFSET;
246 bus_limit = bus_base + HQM_RESERVED_BUS;
247 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
248 + CPM_MMIO_SIZE;
249 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
250 snprintf(tres, sizeof(tres), "HU%d%X", socket, stack);
251 }
252
Arthur Heymans550f55e2022-08-24 14:44:26 +0200253 /* Note, some SKU doesn't provide CPM1 and HQM1 and owns smaller bus ranges
254 accordingly*/
255 if (bus_limit > ri->BusLimit)
256 continue;
257
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800258 printk(BIOS_DEBUG,
259 "\tCreating Dino ResourceTemplate %s for socket: %d, "
260 "stack: %d\n bus_base:0x%x, bus_limit:0x%x\n",
261 tres, socket, stack, bus_base, bus_limit);
262
263 acpigen_write_name(tres);
264 acpigen_write_resourcetemplate_header();
265
Arthur Heymans550f55e2022-08-24 14:44:26 +0200266 acpigen_resource_word(2, 0xc, 0, 0, bus_base, bus_limit, 0x0,
267 (bus_limit - bus_base + 1));
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800268
Arthur Heymans550f55e2022-08-24 14:44:26 +0200269 /* Mem32 resource */
270 if (rlist[i] == DSDT_DINO)
271 acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base,
272 ri->PciResourceMem32Limit, 0x0,
273 (ri->PciResourceMem32Limit
274 - ri->PciResourceMem32Base + 1));
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800275
Arthur Heymans550f55e2022-08-24 14:44:26 +0200276 /* Mem64 resource */
277 acpigen_resource_qword(0, 0xc, 1, 0, mem64_base, mem64_limit, 0,
278 (mem64_limit - mem64_base + 1));
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800279
280 acpigen_write_resourcetemplate_footer();
281 }
282}
283
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200284static 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 -0800285{
286 /*
287 Stacks D .. E (TYPE_UBOX)
288 Scope: UC/UD<socket><0..1> for UBOX[1-2], ResourceTemplate: UT/UU
289 */
290
291 for (int i = 0; i < 2; ++i) {
292 char tres[16];
293 /* write ResourceTemplate resource name */
294 if (i == 0)
295 snprintf(tres, sizeof(tres), "UT%d%X", socket, stack);
296 else
297 snprintf(tres, sizeof(tres), "UU%d%X", socket, stack);
298
299 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n",
300 tres, socket, stack);
301
302 acpigen_write_name(tres);
303 acpigen_write_resourcetemplate_header();
304
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200305 if (!stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800306 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
307 else if (i == 0)
308 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
309 else
310 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusBase + 1,
311 0x0, 1);
312
313 acpigen_write_resourcetemplate_footer();
314 }
315}
316
317
318/*
319 * Add a DSDT ACPI Name field for STACK enable setting.
320 * This is retrieved by the device _STA defined in iiostack.asl
321 */
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200322static 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 -0800323{
324 char stack_sta[16];
325 snprintf(stack_sta, sizeof(stack_sta), "ST%d%X", socket, stack);
326
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200327 if (!stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800328 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_OFF);
329 else
330 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_ON);
331}
332
333void uncore_inject_dsdt(const struct device *device)
334{
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200335 bool stack_enabled;
336
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800337 /* Only add RTxx entries once. */
338 if (device->bus->secondary != 0)
339 return;
340
341 /*
342 Write stack scope - this needs to match RP ACPI scopes.
343 Stacks 0 (TYPE_UBOX_IIO)
344 Scope: PC<socket><stack>, ResourceTemplate: P0RS
345 Stacks 1 .. 5 (TYPE_UBOX_IIO)
346 Scope: PC<socket><stack> & CX<socket><stack>, ResourceTemplate: RBRS
347 Stacks 8 .. B (TYPE_DINO)
348 Scope: DI<socket><stack> for DINO, ResourceTemplate: RBRS
349 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: RBRS
350 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: RBRS
351 Stacks D .. E (TYPE_UBOX)
352 Scope: UC<socket><0..1> for UBOX[1-2], ResourceTemplate: UNRS
353 */
354
355 printk(BIOS_DEBUG, "%s device: %s\n", __func__, dev_path(device));
356
357 acpigen_write_scope("\\_SB");
358
359 /* The _CSR generation must match SPR iiostack.asl. */
360 const IIO_UDS *hob = get_iio_uds();
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200361 /* Iterate over CONFIG_MAX_SOCKET to keep ASL templates and DSDT injection in sync */
362 for (uint8_t socket = 0; socket < CONFIG_MAX_SOCKET; ++socket) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800363 for (int stack = 0; stack < MAX_LOGIC_IIO_STACK; ++stack) {
364 const STACK_RES *ri =
365 &hob->PlatformData.IIO_resource[socket].StackRes[stack];
366
Patrick Rudolphb096d622023-07-14 17:18:18 +0200367 stack_enabled = soc_cpu_is_enabled(socket) &&
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200368 ri->Personality < TYPE_RESERVED;
369
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800370 printk(BIOS_DEBUG, "%s processing socket: %d, stack: %d, type: %d\n",
371 __func__, socket, stack, ri->Personality);
372
373 if (stack <= IioStack5) { // TYPE_UBOX_IIO
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200374 create_dsdt_iou_pci_resource(socket, stack, ri, stack_enabled);
375 create_dsdt_iou_cxl_resource(socket, stack, ri, stack_enabled);
376 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800377 } else if (stack >= IioStack8 && stack <= IioStack11) { // TYPE_DINO
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200378 create_dsdt_dino_resource(socket, stack, ri, stack_enabled);
379 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800380 } else if (stack == IioStack13) { // TYPE_UBOX
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200381 create_dsdt_ubox_resource(socket, stack, ri, stack_enabled);
382 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800383 }
384 }
385 }
386
387 acpigen_pop_len();
388}
389
390/* TODO: See if we can use the common generate_p_state_entries */
391void soc_power_states_generation(int core, int cores_per_package)
392{
393 int ratio_min, ratio_max, ratio_turbo, ratio_step;
394 int coord_type, power_max, power_unit, num_entries;
395 int ratio, power, clock, clock_max;
396 msr_t msr;
397
398 /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
399 msr = rdmsr(MSR_MISC_PWR_MGMT);
400 if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
401 coord_type = SW_ANY;
402 else
403 coord_type = HW_ALL;
404
405 /* Get bus ratio limits and calculate clock speeds */
406 msr = rdmsr(MSR_PLATFORM_INFO);
407 ratio_min = (msr.hi >> (40 - 32)) & 0xff; /* Max Efficiency Ratio */
408
409 /* Determine if this CPU has configurable TDP */
410 if (cpu_config_tdp_levels()) {
411 /* Set max ratio to nominal TDP ratio */
412 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
413 ratio_max = msr.lo & 0xff;
414 } else {
415 /* Max Non-Turbo Ratio */
416 ratio_max = (msr.lo >> 8) & 0xff;
417 }
418 clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ;
419
420 /* Calculate CPU TDP in mW */
421 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
422 power_unit = 2 << ((msr.lo & 0xf) - 1);
423 msr = rdmsr(MSR_PKG_POWER_SKU);
424 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
425
426 /* Write _PCT indicating use of FFixedHW */
427 acpigen_write_empty_PCT();
428
429 /* Write _PPC with no limit on supported P-state */
430 acpigen_write_PPC_NVS();
431
432 /* Write PSD indicating configured coordination type */
433 acpigen_write_PSD_package(core, 1, coord_type);
434
435 /* Add P-state entries in _PSS table */
436 acpigen_write_name("_PSS");
437
438 /* Determine ratio points */
439 ratio_step = PSS_RATIO_STEP;
440 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
441 if (num_entries > PSS_MAX_ENTRIES) {
442 ratio_step += 1;
443 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
444 }
445
446 /* P[T] is Turbo state if enabled */
447 if (get_turbo_state() == TURBO_ENABLED) {
448 /* _PSS package count including Turbo */
449 acpigen_write_package(num_entries + 2);
450
451 msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
452 ratio_turbo = msr.lo & 0xff;
453
454 /* Add entry for Turbo ratio */
455 acpigen_write_PSS_package(clock_max + 1, /* MHz */
456 power_max, /* mW */
457 PSS_LATENCY_TRANSITION, /* lat1 */
458 PSS_LATENCY_BUSMASTER, /* lat2 */
459 ratio_turbo << 8, /* control */
460 ratio_turbo << 8); /* status */
461 } else {
462 /* _PSS package count without Turbo */
463 acpigen_write_package(num_entries + 1);
464 }
465
466 /* First regular entry is max non-turbo ratio */
467 acpigen_write_PSS_package(clock_max, /* MHz */
468 power_max, /* mW */
469 PSS_LATENCY_TRANSITION, /* lat1 */
470 PSS_LATENCY_BUSMASTER, /* lat2 */
471 ratio_max << 8, /* control */
472 ratio_max << 8); /* status */
473
474 /* Generate the remaining entries */
475 for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min;
476 ratio -= ratio_step) {
477
478 /* Calculate power at this ratio */
479 power = common_calculate_power_ratio(power_max, ratio_max, ratio);
480 clock = ratio * CONFIG_CPU_BCLK_MHZ;
481 // clock = 1;
482 acpigen_write_PSS_package(clock, /* MHz */
483 power, /* mW */
484 PSS_LATENCY_TRANSITION, /* lat1 */
485 PSS_LATENCY_BUSMASTER, /* lat2 */
486 ratio << 8, /* control */
487 ratio << 8); /* status */
488 }
489
490 /* Fix package length */
491 acpigen_pop_len();
492}
493
494unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current)
495{
496 struct device *cpu;
497 uint8_t num_cpus = 0;
498
499 for (cpu = all_devices; cpu; cpu = cpu->next) {
500 if ((cpu->path.type != DEVICE_PATH_APIC)
501 || (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
502 continue;
503 }
504 if (!cpu->enabled)
505 continue;
Kyösti Mälkki2e9f0d32023-04-07 23:05:46 +0300506 current = acpi_create_madt_one_lapic(current, num_cpus, cpu->path.apic.apic_id);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800507 num_cpus++;
508 }
509
510 return current;
511}
512
513unsigned long acpi_fill_cedt(unsigned long current)
514{
515 const IIO_UDS *hob = get_iio_uds();
516 union uid {
517 uint32_t data;
518 struct {
519 uint8_t byte0;
520 uint8_t byte1;
521 uint8_t byte2;
522 uint8_t byte3;
523 };
524 } cxl_uid;
525 u32 cxl_ver;
526 u64 base;
527
528 cxl_uid.byte0 = 'C';
529 cxl_uid.byte1 = 'X';
530 /* Loop through all sockets and stacks, add CHBS for each CXL IIO stack */
Patrick Rudolphac028572023-07-14 17:44:33 +0200531 for (uint8_t socket = 0, iio = 0; iio < hob->PlatformData.numofIIO; ++socket) {
532 if (!soc_cpu_is_enabled(socket))
533 continue;
534 iio++;
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800535 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
Patrick Rudolphac028572023-07-14 17:44:33 +0200536 const STACK_RES *ri;
537 ri = &hob->PlatformData.IIO_resource[socket].StackRes[x];
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800538 if (!is_iio_cxl_stack_res(ri))
539 continue;
540 /* uid needs to match with ACPI CXL device ID, eg. acpi/iiostack.asl */
Patrick Rudolphac028572023-07-14 17:44:33 +0200541 cxl_uid.byte2 = socket + '0';
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800542 cxl_uid.byte3 = x + '0';
543 cxl_ver = ACPI_CEDT_CHBS_CXL_VER_1_1;
544 base = ri->Mmio32Base; /* DP RCRB base */
545 current += acpi_create_cedt_chbs((acpi_cedt_chbs_t *)current,
546 cxl_uid.data, cxl_ver, base);
547 }
548 }
549
550 return current;
551}