blob: c609f4fa65f71e781d6ccfa8aebddaf90880a1c7 [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
Patrick Rudolph6e6832d2023-04-04 09:37:30 +020089static void create_dsdt_iou_pci_resource(uint8_t socket, uint8_t stack, const STACK_RES *ri,
90 bool stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -080091{
92 /*
93 Stacks 0 (TYPE_UBOX_IIO)
94 Scope: PC<socket><stack>, ResourceTemplate: P0RS
95 Stacks 1 .. 5 (TYPE_UBOX_IIO)
96 Scope: PC<socket><stack>, ResourceTemplate: RBRS
97 */
98
99 /* Write ResourceTemplate resource name */
100 char tres[16];
101 snprintf(tres, sizeof(tres), "PT%d%X", socket, stack);
102 acpigen_write_name(tres);
103
104 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
105 socket, stack);
106
107 acpigen_write_resourcetemplate_header();
108
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800109 /* Bus Resource */
110 if (stack_enabled) {
111 /* For stack with CXL device, the PCIe bus resource is BusBase only. */
112 if (is_iio_cxl_stack_res(ri))
113 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
114 else
115 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusLimit, 0x0,
116 (ri->BusLimit - ri->BusBase + 1));
117 } else {
118 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
119 }
120
121 /* Additional IO resources on socket 0 bus 0 */
122 if (socket == 0 && stack == 0) {
123 /* ACPI 6.4.2.5 I/O Port Descriptor */
124 acpigen_write_io16(0xCF8, 0xCFF, 0x1, 0x8, 1);
125
126 /* IO decode CF8-CFF */
127 acpigen_resource_word(1, 0xc, 0x3, 0, 0x0000, 0x03AF, 0, 0x03B0);
128 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03E0, 0x0CF7, 0, 0x0918);
129 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03B0, 0x03BB, 0, 0x000C);
130 acpigen_resource_word(1, 0xc, 0x3, 0, 0x03C0, 0x03DF, 0, 0x0020);
131 }
132
133 /* IO resource */
134 if (stack_enabled) {
135 acpigen_resource_word(1, 0xc, 0x3, 0, ri->PciResourceIoBase,
136 ri->PciResourceIoLimit, 0x0,
137 (ri->PciResourceIoLimit - ri->PciResourceIoBase + 1));
138
139 /* Additional Mem32 resources on socket 0 bus 0 */
140 if (socket == 0 && stack == 0) {
141 acpigen_resource_dword(0, 0xc, 3, 0, VGA_BASE_ADDRESS,
142 (VGA_BASE_ADDRESS + VGA_BASE_SIZE - 1), 0x0,
143 VGA_BASE_SIZE);
144 acpigen_resource_dword(0, 0xc, 1, 0, SPI_BASE_ADDRESS,
145 (SPI_BASE_ADDRESS + SPI_BASE_SIZE - 1), 0x0,
146 SPI_BASE_SIZE);
147 }
148
149 /* Mem32 resource */
150 acpigen_resource_dword(
151 0, 0xc, 1, 0, ri->PciResourceMem32Base, ri->PciResourceMem32Limit, 0x0,
152 (ri->PciResourceMem32Limit - ri->PciResourceMem32Base + 1));
153
154 /* Mem64 resource */
155 acpigen_resource_qword(
156 0, 0xc, 1, 0, ri->PciResourceMem64Base, ri->PciResourceMem64Limit, 0x0,
157 (ri->PciResourceMem64Limit - ri->PciResourceMem64Base + 1));
158 } else {
159 /* Zeroed IO resource */
160 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
161
162 /* Zeroed Mem32 resource */
163 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
164
165 /* Zeroed Mem64 resource */
166 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
167 }
168
169 acpigen_write_resourcetemplate_footer();
170}
171
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200172static 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 -0800173{
174 /*
175 Stacks 1 .. 5 (TYPE_UBOX_IIO)
176 Scope: CX<socket><stack>, ResourceTemplate: RBRS
177 */
178 /* write ResourceTemplate resource name */
179 char tres[16];
180 snprintf(tres, sizeof(tres), "CT%d%X", socket, stack);
181 acpigen_write_name(tres);
182
183 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n", tres,
184 socket, stack);
185
186 acpigen_write_resourcetemplate_header();
187
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200188 if (stack_enabled) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800189 /* bus resource, from (BusBase + 1) to BusLimit */
190 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusLimit, 0x0,
191 (ri->BusLimit - ri->BusBase));
192
193 /* IO resource */
194 acpigen_resource_word(1, 0xc, 0x3, 0, ri->IoBase, ri->PciResourceIoBase - 1,
195 0x0, ri->PciResourceIoBase - ri->IoBase);
196
197 /* Mem32 resource */
198 acpigen_resource_dword(0, 0xc, 1, 0, ri->Mmio32Base,
199 ri->PciResourceMem32Base - 1, 0x0,
200 ri->PciResourceMem32Base - ri->Mmio32Base);
201
202 /* Mem64 resource */
203 acpigen_resource_qword(0, 0xc, 1, 0, ri->Mmio64Base,
204 ri->PciResourceMem64Base - 1, 0x0,
205 ri->PciResourceMem64Base - ri->Mmio64Base);
206 } else {
207 /* bus resource, from (BusBase + 1) to BusLimit */
208 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
209
210 /* IO resource */
211 acpigen_resource_word(1, 0, 3, 0, 0, 0, 0, 0);
212
213 /* Mem32 resource */
214 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
215
216 /* Mem64 resource */
217 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
218 }
219
220 acpigen_write_resourcetemplate_footer();
221}
222
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200223static 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 -0800224{
225 /*
226 Stacks 8 .. B (TYPE_DINO)
227 Scope: DI<socket><stack> for DINO, ResourceTemplate: DT
228 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: MT
229 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: HT
230 */
231
232 enum {
233 DSDT_DINO = 0,
234 DSDT_CPM,
235 DSDT_HQM,
236 DSDT_CPM1,
237 DSDT_HQM1
238 };
239 uint8_t rlist[] = {DSDT_DINO, DSDT_CPM, DSDT_HQM, DSDT_CPM1, DSDT_HQM1};
240
241 for (int i = 0; i < ARRAY_SIZE(rlist); ++i) {
242 uint8_t bus_base, bus_limit;
243 uint64_t mem64_base, mem64_limit;
244 char tres[16];
245
246 /* Note, This allocates the resources in a different order than
247 * coreboot (DINO base is last). This causes the kernel to
248 * reallocate the DINO BARs.
249 * TODO: Use the resource settings from coreboot */
250 if (rlist[i] == DSDT_DINO) {
251 bus_base = ri->BusBase;
252 bus_limit = ri->BusBase;
253 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
254 + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
255 mem64_limit = ri->PciResourceMem64Limit;
256 snprintf(tres, sizeof(tres), "DT%d%X", socket, stack);
257 } else if (rlist[i] == DSDT_CPM) {
258 bus_base = ri->BusBase + CPM_BUS_OFFSET;
259 bus_limit = bus_base + CPM_RESERVED_BUS;
260 mem64_base = ri->PciResourceMem64Base;
261 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
262 snprintf(tres, sizeof(tres), "MT%d%X", socket, stack);
263 } else if (rlist[i] == DSDT_HQM) {
264 bus_base = ri->BusBase + HQM_BUS_OFFSET;
265 bus_limit = bus_base + HQM_RESERVED_BUS;
266 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE;
267 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
268 snprintf(tres, sizeof(tres), "HT%d%X", socket, stack);
269 } else if (rlist[i] == DSDT_CPM1) {
270 bus_base = ri->BusBase + CPM1_BUS_OFFSET;
271 bus_limit = bus_base + CPM_RESERVED_BUS;
272 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE;
273 mem64_limit = mem64_base + CPM_MMIO_SIZE - 1;
274 snprintf(tres, sizeof(tres), "MU%d%X", socket, stack);
275 } else { // DSDT_HQM1
276 bus_base = ri->BusBase + HQM1_BUS_OFFSET;
277 bus_limit = bus_base + HQM_RESERVED_BUS;
278 mem64_base = ri->PciResourceMem64Base + CPM_MMIO_SIZE + HQM_MMIO_SIZE
279 + CPM_MMIO_SIZE;
280 mem64_limit = mem64_base + HQM_MMIO_SIZE - 1;
281 snprintf(tres, sizeof(tres), "HU%d%X", socket, stack);
282 }
283
284 printk(BIOS_DEBUG,
285 "\tCreating Dino ResourceTemplate %s for socket: %d, "
286 "stack: %d\n bus_base:0x%x, bus_limit:0x%x\n",
287 tres, socket, stack, bus_base, bus_limit);
288
289 acpigen_write_name(tres);
290 acpigen_write_resourcetemplate_header();
291
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200292 if (stack_enabled) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800293 acpigen_resource_word(2, 0xc, 0, 0, bus_base, bus_limit, 0x0,
294 (bus_limit - bus_base + 1));
295
296 /* Mem32 resource */
297 if (rlist[i] == DSDT_DINO)
298 acpigen_resource_dword(0, 0xc, 1, 0, ri->PciResourceMem32Base,
299 ri->PciResourceMem32Limit, 0x0,
300 (ri->PciResourceMem32Limit
301 - ri->PciResourceMem32Base + 1));
302
303 /* Mem64 resource */
304 acpigen_resource_qword(0, 0xc, 1, 0, mem64_base, mem64_limit, 0,
305 (mem64_limit - mem64_base + 1));
306 } else {
307 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
308
309 /* Mem32 resource */
310 if (rlist[i] == DSDT_DINO)
311 acpigen_resource_dword(0, 0, 1, 0, 0, 0, 0, 0);
312
313 /* Mem64 resource */
314 acpigen_resource_qword(0, 0, 1, 0, 0, 0, 0, 0);
315 }
316
317 acpigen_write_resourcetemplate_footer();
318 }
319}
320
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200321static 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 -0800322{
323 /*
324 Stacks D .. E (TYPE_UBOX)
325 Scope: UC/UD<socket><0..1> for UBOX[1-2], ResourceTemplate: UT/UU
326 */
327
328 for (int i = 0; i < 2; ++i) {
329 char tres[16];
330 /* write ResourceTemplate resource name */
331 if (i == 0)
332 snprintf(tres, sizeof(tres), "UT%d%X", socket, stack);
333 else
334 snprintf(tres, sizeof(tres), "UU%d%X", socket, stack);
335
336 printk(BIOS_DEBUG, "\tCreating ResourceTemplate %s for socket: %d, stack: %d\n",
337 tres, socket, stack);
338
339 acpigen_write_name(tres);
340 acpigen_write_resourcetemplate_header();
341
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200342 if (!stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800343 acpigen_resource_word(2, 0, 0, 0, 0, 0, 0, 0);
344 else if (i == 0)
345 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase, ri->BusBase, 0x0, 1);
346 else
347 acpigen_resource_word(2, 0xc, 0, 0, ri->BusBase + 1, ri->BusBase + 1,
348 0x0, 1);
349
350 acpigen_write_resourcetemplate_footer();
351 }
352}
353
354
355/*
356 * Add a DSDT ACPI Name field for STACK enable setting.
357 * This is retrieved by the device _STA defined in iiostack.asl
358 */
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200359static 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 -0800360{
361 char stack_sta[16];
362 snprintf(stack_sta, sizeof(stack_sta), "ST%d%X", socket, stack);
363
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200364 if (!stack_enabled)
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800365 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_OFF);
366 else
367 acpigen_write_name_integer(stack_sta, ACPI_STATUS_DEVICE_ALL_ON);
368}
369
370void uncore_inject_dsdt(const struct device *device)
371{
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200372 bool stack_enabled;
373
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800374 /* Only add RTxx entries once. */
375 if (device->bus->secondary != 0)
376 return;
377
378 /*
379 Write stack scope - this needs to match RP ACPI scopes.
380 Stacks 0 (TYPE_UBOX_IIO)
381 Scope: PC<socket><stack>, ResourceTemplate: P0RS
382 Stacks 1 .. 5 (TYPE_UBOX_IIO)
383 Scope: PC<socket><stack> & CX<socket><stack>, ResourceTemplate: RBRS
384 Stacks 8 .. B (TYPE_DINO)
385 Scope: DI<socket><stack> for DINO, ResourceTemplate: RBRS
386 Scope: CP<socket><stack> for CPM (i.e., QAT), ResourceTemplate: RBRS
387 Scope: HQ<socket><stack> for HQM (i.e., DLB), ResourceTemplate: RBRS
388 Stacks D .. E (TYPE_UBOX)
389 Scope: UC<socket><0..1> for UBOX[1-2], ResourceTemplate: UNRS
390 */
391
392 printk(BIOS_DEBUG, "%s device: %s\n", __func__, dev_path(device));
393
394 acpigen_write_scope("\\_SB");
395
396 /* The _CSR generation must match SPR iiostack.asl. */
397 const IIO_UDS *hob = get_iio_uds();
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200398 /* Iterate over CONFIG_MAX_SOCKET to keep ASL templates and DSDT injection in sync */
399 for (uint8_t socket = 0; socket < CONFIG_MAX_SOCKET; ++socket) {
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800400 for (int stack = 0; stack < MAX_LOGIC_IIO_STACK; ++stack) {
401 const STACK_RES *ri =
402 &hob->PlatformData.IIO_resource[socket].StackRes[stack];
403
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200404 stack_enabled = hob->PlatformData.IIO_resource[socket].Valid &&
405 ri->Personality < TYPE_RESERVED;
406
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800407 printk(BIOS_DEBUG, "%s processing socket: %d, stack: %d, type: %d\n",
408 __func__, socket, stack, ri->Personality);
409
410 if (stack <= IioStack5) { // TYPE_UBOX_IIO
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200411 create_dsdt_iou_pci_resource(socket, stack, ri, stack_enabled);
412 create_dsdt_iou_cxl_resource(socket, stack, ri, stack_enabled);
413 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800414 } else if (stack >= IioStack8 && stack <= IioStack11) { // TYPE_DINO
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200415 create_dsdt_dino_resource(socket, stack, ri, stack_enabled);
416 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800417 } else if (stack == IioStack13) { // TYPE_UBOX
Patrick Rudolph6e6832d2023-04-04 09:37:30 +0200418 create_dsdt_ubox_resource(socket, stack, ri, stack_enabled);
419 create_dsdt_stack_sta(socket, stack, ri, stack_enabled);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800420 }
421 }
422 }
423
424 acpigen_pop_len();
425}
426
427/* TODO: See if we can use the common generate_p_state_entries */
428void soc_power_states_generation(int core, int cores_per_package)
429{
430 int ratio_min, ratio_max, ratio_turbo, ratio_step;
431 int coord_type, power_max, power_unit, num_entries;
432 int ratio, power, clock, clock_max;
433 msr_t msr;
434
435 /* Determine P-state coordination type from MISC_PWR_MGMT[0] */
436 msr = rdmsr(MSR_MISC_PWR_MGMT);
437 if (msr.lo & MISC_PWR_MGMT_EIST_HW_DIS)
438 coord_type = SW_ANY;
439 else
440 coord_type = HW_ALL;
441
442 /* Get bus ratio limits and calculate clock speeds */
443 msr = rdmsr(MSR_PLATFORM_INFO);
444 ratio_min = (msr.hi >> (40 - 32)) & 0xff; /* Max Efficiency Ratio */
445
446 /* Determine if this CPU has configurable TDP */
447 if (cpu_config_tdp_levels()) {
448 /* Set max ratio to nominal TDP ratio */
449 msr = rdmsr(MSR_CONFIG_TDP_NOMINAL);
450 ratio_max = msr.lo & 0xff;
451 } else {
452 /* Max Non-Turbo Ratio */
453 ratio_max = (msr.lo >> 8) & 0xff;
454 }
455 clock_max = ratio_max * CONFIG_CPU_BCLK_MHZ;
456
457 /* Calculate CPU TDP in mW */
458 msr = rdmsr(MSR_PKG_POWER_SKU_UNIT);
459 power_unit = 2 << ((msr.lo & 0xf) - 1);
460 msr = rdmsr(MSR_PKG_POWER_SKU);
461 power_max = ((msr.lo & 0x7fff) / power_unit) * 1000;
462
463 /* Write _PCT indicating use of FFixedHW */
464 acpigen_write_empty_PCT();
465
466 /* Write _PPC with no limit on supported P-state */
467 acpigen_write_PPC_NVS();
468
469 /* Write PSD indicating configured coordination type */
470 acpigen_write_PSD_package(core, 1, coord_type);
471
472 /* Add P-state entries in _PSS table */
473 acpigen_write_name("_PSS");
474
475 /* Determine ratio points */
476 ratio_step = PSS_RATIO_STEP;
477 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
478 if (num_entries > PSS_MAX_ENTRIES) {
479 ratio_step += 1;
480 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
481 }
482
483 /* P[T] is Turbo state if enabled */
484 if (get_turbo_state() == TURBO_ENABLED) {
485 /* _PSS package count including Turbo */
486 acpigen_write_package(num_entries + 2);
487
488 msr = rdmsr(MSR_TURBO_RATIO_LIMIT);
489 ratio_turbo = msr.lo & 0xff;
490
491 /* Add entry for Turbo ratio */
492 acpigen_write_PSS_package(clock_max + 1, /* MHz */
493 power_max, /* mW */
494 PSS_LATENCY_TRANSITION, /* lat1 */
495 PSS_LATENCY_BUSMASTER, /* lat2 */
496 ratio_turbo << 8, /* control */
497 ratio_turbo << 8); /* status */
498 } else {
499 /* _PSS package count without Turbo */
500 acpigen_write_package(num_entries + 1);
501 }
502
503 /* First regular entry is max non-turbo ratio */
504 acpigen_write_PSS_package(clock_max, /* MHz */
505 power_max, /* mW */
506 PSS_LATENCY_TRANSITION, /* lat1 */
507 PSS_LATENCY_BUSMASTER, /* lat2 */
508 ratio_max << 8, /* control */
509 ratio_max << 8); /* status */
510
511 /* Generate the remaining entries */
512 for (ratio = ratio_min + ((num_entries - 1) * ratio_step); ratio >= ratio_min;
513 ratio -= ratio_step) {
514
515 /* Calculate power at this ratio */
516 power = common_calculate_power_ratio(power_max, ratio_max, ratio);
517 clock = ratio * CONFIG_CPU_BCLK_MHZ;
518 // clock = 1;
519 acpigen_write_PSS_package(clock, /* MHz */
520 power, /* mW */
521 PSS_LATENCY_TRANSITION, /* lat1 */
522 PSS_LATENCY_BUSMASTER, /* lat2 */
523 ratio << 8, /* control */
524 ratio << 8); /* status */
525 }
526
527 /* Fix package length */
528 acpigen_pop_len();
529}
530
531unsigned long xeonsp_acpi_create_madt_lapics(unsigned long current)
532{
533 struct device *cpu;
534 uint8_t num_cpus = 0;
535
536 for (cpu = all_devices; cpu; cpu = cpu->next) {
537 if ((cpu->path.type != DEVICE_PATH_APIC)
538 || (cpu->bus->dev->path.type != DEVICE_PATH_CPU_CLUSTER)) {
539 continue;
540 }
541 if (!cpu->enabled)
542 continue;
Kyösti Mälkki2e9f0d32023-04-07 23:05:46 +0300543 current = acpi_create_madt_one_lapic(current, num_cpus, cpu->path.apic.apic_id);
Jonathan Zhangd80e6f22023-01-25 11:35:03 -0800544 num_cpus++;
545 }
546
547 return current;
548}
549
550unsigned long acpi_fill_cedt(unsigned long current)
551{
552 const IIO_UDS *hob = get_iio_uds();
553 union uid {
554 uint32_t data;
555 struct {
556 uint8_t byte0;
557 uint8_t byte1;
558 uint8_t byte2;
559 uint8_t byte3;
560 };
561 } cxl_uid;
562 u32 cxl_ver;
563 u64 base;
564
565 cxl_uid.byte0 = 'C';
566 cxl_uid.byte1 = 'X';
567 /* Loop through all sockets and stacks, add CHBS for each CXL IIO stack */
568 for (uint8_t s = 0; s < hob->PlatformData.numofIIO; ++s) {
569 for (int x = 0; x < MAX_LOGIC_IIO_STACK; ++x) {
570 const STACK_RES *ri = &hob->PlatformData.IIO_resource[s].StackRes[x];
571 if (!is_iio_cxl_stack_res(ri))
572 continue;
573 /* uid needs to match with ACPI CXL device ID, eg. acpi/iiostack.asl */
574 cxl_uid.byte2 = s + '0';
575 cxl_uid.byte3 = x + '0';
576 cxl_ver = ACPI_CEDT_CHBS_CXL_VER_1_1;
577 base = ri->Mmio32Base; /* DP RCRB base */
578 current += acpi_create_cedt_chbs((acpi_cedt_chbs_t *)current,
579 cxl_uid.data, cxl_ver, base);
580 }
581 }
582
583 return current;
584}