soc/intel/pantherlake: Remove soc_info.[hc] interface
[coreboot2.git] / src / soc / intel / common / block / acpi / acpi.c
blobd683726d866b619bfa3d3df3ee187abc298326a6
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
3 #include <acpi/acpi.h>
4 #include <acpi/acpi_pm.h>
5 #include <acpi/acpigen.h>
6 #include <arch/ioapic.h>
7 #include <arch/smp/mpspec.h>
8 #include <console/console.h>
9 #include <cpu/cpu.h>
10 #include <cpu/intel/common/common.h>
11 #include <cpu/intel/msr.h>
12 #include <cpu/intel/turbo.h>
13 #include <cpu/x86/lapic.h>
14 #include <intelblocks/acpi_wake_source.h>
15 #include <intelblocks/acpi.h>
16 #include <intelblocks/lpc_lib.h>
17 #include <intelblocks/pmclib.h>
18 #include <intelblocks/sgx.h>
19 #include <intelblocks/tco.h>
20 #include <intelblocks/uart.h>
21 #include <soc/gpio.h>
22 #include <soc/intel/common/tco.h>
23 #include <soc/iomap.h>
24 #include <soc/pm.h>
26 #define CPUID_6_EAX_ISST (1 << 7)
28 #define ACPI_SCI_IRQ 9
30 void ioapic_get_sci_pin(u8 *gsi, u8 *irq, u8 *flags)
32 int sci_irq = ACPI_SCI_IRQ;
33 uint32_t scis;
35 scis = soc_read_sci_irq_select();
36 scis &= SCI_IRQ_SEL;
37 scis >>= SCI_IRQ_ADJUST;
39 /* Determine how SCI is routed. */
40 switch (scis) {
41 case SCIS_IRQ9:
42 case SCIS_IRQ10:
43 case SCIS_IRQ11:
44 sci_irq = scis - SCIS_IRQ9 + 9;
45 break;
46 case SCIS_IRQ20:
47 case SCIS_IRQ21:
48 case SCIS_IRQ22:
49 case SCIS_IRQ23:
50 sci_irq = scis - SCIS_IRQ20 + 20;
51 break;
52 default:
53 printk(BIOS_DEBUG, "Invalid SCI route! Defaulting to IRQ%d.\n", sci_irq);
54 break;
57 *gsi = sci_irq;
58 *irq = (sci_irq < 16) ? sci_irq : ACPI_SCI_IRQ;
59 *flags = MP_IRQ_TRIGGER_LEVEL | soc_madt_sci_irq_polarity(sci_irq);
61 printk(BIOS_DEBUG, "SCI is IRQ %d, GSI %d\n", *irq, *gsi);
65 static const uintptr_t default_ioapic_bases[] = { IO_APIC_ADDR };
67 __weak size_t soc_get_ioapic_info(const uintptr_t *ioapic_bases[])
69 *ioapic_bases = default_ioapic_bases;
70 return ARRAY_SIZE(default_ioapic_bases);
73 unsigned long acpi_fill_madt(unsigned long current)
75 const uintptr_t *ioapic_table;
76 size_t ioapic_entries;
78 /* Local APICs */
79 if (!CONFIG(ACPI_COMMON_MADT_LAPIC))
80 current = acpi_create_madt_lapics_with_nmis_hybrid(current);
82 /* IOAPIC */
83 ioapic_entries = soc_get_ioapic_info(&ioapic_table);
85 /* Default SOC IOAPIC entry */
86 ASSERT(ioapic_table[0] == IO_APIC_ADDR);
88 for (int i = 1; i < ioapic_entries; i++)
89 current += acpi_create_madt_ioapic_from_hw((void *)current, ioapic_table[i]);
91 return current;
94 void acpi_fill_fadt(acpi_fadt_t *fadt)
96 const uint16_t pmbase = ACPI_BASE_ADDRESS;
99 fadt->pm1a_evt_blk = pmbase + PM1_STS;
100 fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
102 fadt->gpe0_blk = pmbase + GPE0_STS(0);
104 fadt->pm1_evt_len = 4;
105 fadt->pm1_cnt_len = 2;
107 /* GPE0 STS/EN pairs each 32 bits wide. */
108 fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
110 fadt->gpe1_blk = 0;
111 if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_USE_GPE1)) {
112 fadt->gpe1_blk = pmbase + GPE1_STS(0);
113 fadt->gpe1_blk_len = 2 * GPE1_REG_MAX * sizeof(uint32_t);
115 * NOTE: gpe1 is after gpe0, which has _STS and _EN register sets.
116 * gpe1_base is the starting bit offset for GPE1.
118 fadt->gpe1_base = fadt->gpe0_blk_len / 2 * 8;
121 fill_fadt_extended_pm_io(fadt);
123 fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
124 ACPI_FADT_SLEEP_BUTTON |
125 ACPI_FADT_SEALED_CASE | ACPI_FADT_S4_RTC_WAKE;
127 if (CONFIG(USE_PM_ACPI_TIMER))
128 fadt->flags |= ACPI_FADT_PLATFORM_CLOCK;
131 unsigned long southbridge_write_acpi_tables(const struct device *device,
132 unsigned long current,
133 struct acpi_rsdp *rsdp)
135 if (CONFIG(SOC_INTEL_COMMON_BLOCK_UART)) {
136 current = acpi_write_dbg2_pci_uart(rsdp, current,
137 uart_get_device(),
138 ACPI_ACCESS_SIZE_DWORD_ACCESS);
141 return acpi_write_hpet(device, current, rsdp);
144 __weak
145 void acpi_fill_soc_wake(uint32_t *pm1_en, uint32_t *gpe0_en,
146 const struct chipset_power_state *ps)
151 * Save wake source information for calculating ACPI _SWS values
153 * @pm1: PM1_STS register with only enabled events set
154 * @gpe0: GPE0_STS registers with only enabled events set
156 * return the number of registers in the gpe0 array
159 int soc_fill_acpi_wake(const struct chipset_power_state *ps, uint32_t *pm1, uint32_t **gpe0)
161 static uint32_t gpe0_sts[GPE0_REG_MAX];
162 uint32_t gpe0_en[GPE0_REG_MAX];
163 uint32_t pm1_en;
164 int i;
167 * PM1_EN to check the basic wake events which can happen through
168 * powerbtn or any other wake source like lidopen, key board press etc.
170 pm1_en = ps->pm1_en;
171 pm1_en |= WAK_STS | PWRBTN_EN;
173 memcpy(gpe0_en, ps->gpe0_en, sizeof(gpe0_en));
175 acpi_fill_soc_wake(&pm1_en, gpe0_en, ps);
177 *pm1 = ps->pm1_sts & pm1_en;
179 /* Mask off GPE0 status bits that are not enabled */
180 *gpe0 = &gpe0_sts[0];
181 for (i = 0; i < GPE0_REG_MAX; i++)
182 gpe0_sts[i] = ps->gpe0_sts[i] & gpe0_en[i];
184 return GPE0_REG_MAX;
187 int common_calculate_power_ratio(int tdp, int p1_ratio, int ratio)
189 u32 m;
190 u32 power;
193 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
195 * Power = (ratio / p1_ratio) * m * tdp
198 m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
199 m = (m * m) / 1000;
201 power = ((ratio * 100000 / p1_ratio) / 100);
202 power *= (m / 100) * (tdp / 1000);
203 power /= 1000;
205 return power;
208 static void generate_c_state_entries(void)
210 const acpi_cstate_t *c_state_map;
211 size_t entries;
213 c_state_map = soc_get_cstate_map(&entries);
215 /* Generate C-state tables */
216 acpigen_write_CST_package(c_state_map, entries);
219 void generate_p_state_entries(int core, int cores_per_package)
221 int ratio_min, ratio_max, ratio_turbo, ratio_step;
222 int coord_type, power_max, num_entries;
223 int ratio, power, clock, clock_max;
224 bool turbo;
226 coord_type = cpu_get_coord_type();
227 ratio_min = cpu_get_min_ratio();
228 ratio_max = cpu_get_max_ratio();
229 clock_max = (ratio_max * cpu_get_bus_clock()) / KHz;
230 turbo = (get_turbo_state() == TURBO_ENABLED);
232 /* Calculate CPU TDP in mW */
233 power_max = cpu_get_power_max();
235 /* Write _PCT indicating use of FFixedHW */
236 acpigen_write_empty_PCT();
238 /* Write _PPC with no limit on supported P-state */
239 acpigen_write_PPC_NVS();
240 /* Write PSD indicating configured coordination type */
241 acpigen_write_PSD_package(core, 1, coord_type);
243 /* Add P-state entries in _PSS table */
244 acpigen_write_name("_PSS");
246 /* Determine ratio points */
247 ratio_step = PSS_RATIO_STEP;
248 do {
249 num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
250 if (((ratio_max - ratio_min) % ratio_step) > 0)
251 num_entries += 1;
252 if (turbo)
253 num_entries += 1;
254 if (num_entries > PSS_MAX_ENTRIES)
255 ratio_step += 1;
256 } while (num_entries > PSS_MAX_ENTRIES);
258 /* _PSS package count depends on Turbo */
259 acpigen_write_package(num_entries);
261 /* P[T] is Turbo state if enabled */
262 if (turbo) {
263 ratio_turbo = cpu_get_max_turbo_ratio();
265 /* Add entry for Turbo ratio */
266 acpigen_write_PSS_package(clock_max + 1, /* MHz */
267 power_max, /* mW */
268 PSS_LATENCY_TRANSITION,/* lat1 */
269 PSS_LATENCY_BUSMASTER,/* lat2 */
270 ratio_turbo << 8, /* control */
271 ratio_turbo << 8); /* status */
272 num_entries -= 1;
275 /* First regular entry is max non-turbo ratio */
276 acpigen_write_PSS_package(clock_max, /* MHz */
277 power_max, /* mW */
278 PSS_LATENCY_TRANSITION,/* lat1 */
279 PSS_LATENCY_BUSMASTER,/* lat2 */
280 ratio_max << 8, /* control */
281 ratio_max << 8); /* status */
282 num_entries -= 1;
284 /* Generate the remaining entries */
285 for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
286 ratio >= ratio_min; ratio -= ratio_step) {
287 /* Calculate power at this ratio */
288 power = common_calculate_power_ratio(power_max, ratio_max, ratio);
289 clock = (ratio * cpu_get_bus_clock()) / KHz;
291 acpigen_write_PSS_package(clock, /* MHz */
292 power, /* mW */
293 PSS_LATENCY_TRANSITION,/* lat1 */
294 PSS_LATENCY_BUSMASTER,/* lat2 */
295 ratio << 8, /* control */
296 ratio << 8); /* status */
298 /* Fix package length */
299 acpigen_pop_len();
302 __weak acpi_tstate_t *soc_get_tss_table(int *entries)
304 *entries = 0;
305 return NULL;
308 void generate_t_state_entries(int core, int cores_per_package)
310 acpi_tstate_t *soc_tss_table;
311 int entries;
313 soc_tss_table = soc_get_tss_table(&entries);
314 if (entries == 0)
315 return;
317 /* Indicate SW_ALL coordination for T-states */
318 acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
320 /* Indicate FixedHW so OS will use MSR */
321 acpigen_write_empty_PTC();
323 /* Set NVS controlled T-state limit */
324 acpigen_write_TPC("\\TLVL");
326 /* Write TSS table for MSR access */
327 acpigen_write_TSS_package(entries, soc_tss_table);
330 static void generate_cppc_entries(int core_id)
332 u32 version = CPPC_VERSION_2;
334 if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID))
335 version = CPPC_VERSION_3;
337 if (!(CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPPC) &&
338 cpuid_eax(6) & CPUID_6_EAX_ISST))
339 return;
341 /* Generate GCPC package in first logical core */
342 if (core_id == 0) {
343 struct cppc_config cppc_config;
344 cpu_init_cppc_config(&cppc_config, version);
345 acpigen_write_CPPC_package(&cppc_config);
348 /* Write _CPC entry for each logical core */
349 if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID))
350 acpigen_write_CPPC_hybrid_method(core_id);
351 else
352 acpigen_write_CPPC_method();
355 __weak void soc_power_states_generation(int core_id,
356 int cores_per_package)
360 static void generate_cpu_entry(int cpu, int core, int cores_per_package)
362 /* Generate processor \_SB.CPUx */
363 acpigen_write_processor_device(cpu * cores_per_package + core);
365 /* Generate C-state tables */
366 generate_c_state_entries();
368 generate_cppc_entries(core);
370 /* Soc specific power states generation */
371 soc_power_states_generation(core, cores_per_package);
373 acpigen_write_processor_device_end();
376 void generate_cpu_entries(const struct device *device)
378 int core_id, cpu_id;
379 int totalcores = dev_count_cpu();
380 unsigned int num_virt;
381 unsigned int num_phys;
383 cpu_read_topology(&num_phys, &num_virt);
385 int numcpus = totalcores / num_virt;
387 printk(BIOS_DEBUG, "Found %d CPU(s) with %d/%d physical/logical core(s) each.\n",
388 numcpus, num_phys, num_virt);
390 for (cpu_id = 0; cpu_id < numcpus; cpu_id++)
391 for (core_id = 0; core_id < num_virt; core_id++)
392 generate_cpu_entry(cpu_id, core_id, num_virt);
394 /* PPKG is usually used for thermal management
395 of the first and only package. */
396 acpigen_write_processor_package("PPKG", 0, num_virt);
398 /* Add a method to notify processor nodes */
399 acpigen_write_processor_cnot(num_virt);
401 if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX_ENABLE))
402 sgx_fill_ssdt();
406 static bool fill_wdat_timeout_entry(acpi_wdat_entry_t *entry)
408 uint16_t tcobase = tco_get_bar();
410 if (tcobase == 0)
411 return false;
413 memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
415 entry->action = ACPI_WDAT_SET_COUNTDOWN;
416 entry->instruction = ACPI_WDAT_WRITE_COUNTDOWN | ACPI_WDAT_PRESERVE_REGISTER;
417 entry->mask = TCO_TMR_MASK;
418 entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
419 entry->register_region.addrl = tcobase + TCO_TMR;
420 entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_WORD;
422 return true;
425 static bool fill_wdat_boot_status_entry(acpi_wdat_entry_t *entry, uint8_t action,
426 uint8_t instruction, uint32_t value)
428 uint16_t tcobase = tco_get_bar();
430 if (tcobase == 0)
431 return false;
433 memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
435 entry->action = action;
436 entry->instruction = instruction;
437 entry->value = value;
438 entry->mask = TCO2_STS_SECOND_TO;
439 entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
440 entry->register_region.addrl = tcobase + TCO_MESSAGE1;
441 entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_BYTE;
443 return true;
446 static bool fill_wdat_run_state_entry(acpi_wdat_entry_t *entry, uint8_t action,
447 uint8_t instruction, uint32_t value)
449 uint16_t tcobase = tco_get_bar();
451 if (tcobase == 0)
452 return false;
454 memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
456 entry->action = action;
457 entry->instruction = instruction;
458 entry->value = value;
459 entry->mask = TCO1_TMR_HLT;
460 entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
461 entry->register_region.addrl = tcobase + TCO1_CNT;
462 entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_WORD;
464 return true;
467 static bool fill_wdat_ping_entry(acpi_wdat_entry_t *entry)
469 uint16_t tcobase = tco_get_bar();
471 if (tcobase == 0)
472 return false;
474 memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
476 entry->action = ACPI_WDAT_RESET;
477 entry->instruction = ACPI_WDAT_WRITE_VALUE;
478 entry->value = 0x01;
479 entry->mask = 0x01;
480 entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
481 entry->register_region.addrl = tcobase + TCO_RLD;
482 entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_WORD;
484 return true;
487 unsigned long acpi_soc_fill_wdat(acpi_wdat_t *wdat, unsigned long current)
489 if (!wdat)
490 return current;
492 uint16_t tcobase = tco_get_bar();
494 if (tcobase == 0)
495 goto out_err;
497 wdat->pci_segment = 0xff;
498 wdat->pci_bus = 0xff;
499 wdat->pci_device = 0xff;
500 wdat->pci_function = 0xff;
502 wdat->timer_period = tco_get_timer_period();
503 wdat->min_count = tco_get_timer_min_value();
504 wdat->max_count = tco_get_timer_max_value();
505 wdat->flags = ACPI_WDAT_FLAG_ENABLED;
506 wdat->entries = 0;
508 acpi_wdat_entry_t *entry = (acpi_wdat_entry_t *)current;
510 /* Write countdown */
511 if (!fill_wdat_timeout_entry(entry))
512 goto out_err;
514 entry++;
516 /* Get boot status */
517 if (!fill_wdat_boot_status_entry(entry, ACPI_WDAT_GET_STATUS,
518 ACPI_WDAT_READ_VALUE, TCO2_STS_SECOND_TO))
519 goto out_err;
521 entry++;
523 /* Set boot status */
524 if (!fill_wdat_boot_status_entry(entry, ACPI_WDAT_SET_STATUS,
525 ACPI_WDAT_WRITE_VALUE | ACPI_WDAT_PRESERVE_REGISTER,
527 goto out_err;
529 entry++;
531 /* Get running status */
532 if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_GET_RUNNING_STATE,
533 ACPI_WDAT_READ_VALUE, 0))
534 goto out_err;
536 entry++;
538 /* Start the watchdog */
539 if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_SET_RUNNING_STATE,
540 ACPI_WDAT_WRITE_VALUE | ACPI_WDAT_PRESERVE_REGISTER,
542 goto out_err;
544 entry++;
546 /* Get stopped status */
547 if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_GET_STOPPED_STATE,
548 ACPI_WDAT_READ_VALUE, TCO1_TMR_HLT))
549 goto out_err;
551 entry++;
553 /* Stop the watchdog */
554 if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_SET_STOPPED_STATE,
555 ACPI_WDAT_WRITE_VALUE | ACPI_WDAT_PRESERVE_REGISTER,
556 TCO1_TMR_HLT))
557 goto out_err;
559 entry++;
561 /* Ping */
562 if (!fill_wdat_ping_entry(entry))
563 goto out_err;
565 entry++;
567 wdat->entries = ((unsigned long)entry - current) / sizeof(acpi_wdat_entry_t);
569 return (unsigned long)entry;
571 out_err:
572 wdat->flags = ACPI_WDAT_FLAG_DISABLED;
573 printk(BIOS_ERR, "Fail to populate WDAT ACPI Table");
575 return current;