xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/acpi/acpi.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
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>
25 
26 #define  CPUID_6_EAX_ISST	(1 << 7)
27 
28 #define ACPI_SCI_IRQ 9
29 
ioapic_get_sci_pin(u8 * gsi,u8 * irq,u8 * flags)30 void ioapic_get_sci_pin(u8 *gsi, u8 *irq, u8 *flags)
31 {
32 	int sci_irq = ACPI_SCI_IRQ;
33 	uint32_t scis;
34 
35 	scis = soc_read_sci_irq_select();
36 	scis &= SCI_IRQ_SEL;
37 	scis >>= SCI_IRQ_ADJUST;
38 
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;
55 	}
56 
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);
60 
61 	printk(BIOS_DEBUG, "SCI is IRQ %d, GSI %d\n", *irq, *gsi);
62 }
63 
64 
65 static const uintptr_t default_ioapic_bases[] = { IO_APIC_ADDR };
66 
soc_get_ioapic_info(const uintptr_t * ioapic_bases[])67 __weak size_t soc_get_ioapic_info(const uintptr_t *ioapic_bases[])
68 {
69 	*ioapic_bases = default_ioapic_bases;
70 	return ARRAY_SIZE(default_ioapic_bases);
71 }
72 
acpi_fill_madt(unsigned long current)73 unsigned long acpi_fill_madt(unsigned long current)
74 {
75 	const uintptr_t *ioapic_table;
76 	size_t ioapic_entries;
77 
78 	/* Local APICs */
79 	if (!CONFIG(ACPI_COMMON_MADT_LAPIC))
80 		current = acpi_create_madt_lapics_with_nmis_hybrid(current);
81 
82 	/* IOAPIC */
83 	ioapic_entries = soc_get_ioapic_info(&ioapic_table);
84 
85 	/* Default SOC IOAPIC entry */
86 	ASSERT(ioapic_table[0] == IO_APIC_ADDR);
87 
88 	for (int i = 1; i < ioapic_entries; i++)
89 		current += acpi_create_madt_ioapic_from_hw((void *)current, ioapic_table[i]);
90 
91 	return current;
92 }
93 
acpi_fill_fadt(acpi_fadt_t * fadt)94 void acpi_fill_fadt(acpi_fadt_t *fadt)
95 {
96 	const uint16_t pmbase = ACPI_BASE_ADDRESS;
97 
98 
99 	fadt->pm1a_evt_blk = pmbase + PM1_STS;
100 	fadt->pm1a_cnt_blk = pmbase + PM1_CNT;
101 
102 	fadt->gpe0_blk = pmbase + GPE0_STS(0);
103 
104 	fadt->pm1_evt_len = 4;
105 	fadt->pm1_cnt_len = 2;
106 
107 	/* GPE0 STS/EN pairs each 32 bits wide. */
108 	fadt->gpe0_blk_len = 2 * GPE0_REG_MAX * sizeof(uint32_t);
109 
110 	fill_fadt_extended_pm_io(fadt);
111 
112 	fadt->flags |= ACPI_FADT_WBINVD | ACPI_FADT_C1_SUPPORTED |
113 			ACPI_FADT_SLEEP_BUTTON |
114 			ACPI_FADT_SEALED_CASE | ACPI_FADT_S4_RTC_WAKE;
115 
116 	if (CONFIG(USE_PM_ACPI_TIMER))
117 		fadt->flags |= ACPI_FADT_PLATFORM_CLOCK;
118 }
119 
southbridge_write_acpi_tables(const struct device * device,unsigned long current,struct acpi_rsdp * rsdp)120 unsigned long southbridge_write_acpi_tables(const struct device *device,
121 					    unsigned long current,
122 					    struct acpi_rsdp *rsdp)
123 {
124 	if (CONFIG(SOC_INTEL_COMMON_BLOCK_UART)) {
125 		current = acpi_write_dbg2_pci_uart(rsdp, current,
126 						uart_get_device(),
127 						ACPI_ACCESS_SIZE_DWORD_ACCESS);
128 	}
129 
130 	return acpi_write_hpet(device, current, rsdp);
131 }
132 
133 __weak
acpi_fill_soc_wake(uint32_t * pm1_en,uint32_t * gpe0_en,const struct chipset_power_state * ps)134 void acpi_fill_soc_wake(uint32_t *pm1_en, uint32_t *gpe0_en,
135 			const struct chipset_power_state *ps)
136 {
137 }
138 
139 /*
140  * Save wake source information for calculating ACPI _SWS values
141  *
142  * @pm1:  PM1_STS register with only enabled events set
143  * @gpe0: GPE0_STS registers with only enabled events set
144  *
145  * return the number of registers in the gpe0 array
146  */
147 
soc_fill_acpi_wake(const struct chipset_power_state * ps,uint32_t * pm1,uint32_t ** gpe0)148 int soc_fill_acpi_wake(const struct chipset_power_state *ps, uint32_t *pm1, uint32_t **gpe0)
149 {
150 	static uint32_t gpe0_sts[GPE0_REG_MAX];
151 	uint32_t gpe0_en[GPE0_REG_MAX];
152 	uint32_t pm1_en;
153 	int i;
154 
155 	/*
156 	 * PM1_EN to check the basic wake events which can happen through
157 	 * powerbtn or any other wake source like lidopen, key board press etc.
158 	 */
159 	pm1_en = ps->pm1_en;
160 	pm1_en |= WAK_STS | PWRBTN_EN;
161 
162 	memcpy(gpe0_en, ps->gpe0_en, sizeof(gpe0_en));
163 
164 	acpi_fill_soc_wake(&pm1_en, gpe0_en, ps);
165 
166 	*pm1 = ps->pm1_sts & pm1_en;
167 
168 	/* Mask off GPE0 status bits that are not enabled */
169 	*gpe0 = &gpe0_sts[0];
170 	for (i = 0; i < GPE0_REG_MAX; i++)
171 		gpe0_sts[i] = ps->gpe0_sts[i] & gpe0_en[i];
172 
173 	return GPE0_REG_MAX;
174 }
175 
common_calculate_power_ratio(int tdp,int p1_ratio,int ratio)176 int common_calculate_power_ratio(int tdp, int p1_ratio, int ratio)
177 {
178 	u32 m;
179 	u32 power;
180 
181 	/*
182 	 * M = ((1.1 - ((p1_ratio - ratio) * 0.00625)) / 1.1) ^ 2
183 	 *
184 	 * Power = (ratio / p1_ratio) * m * tdp
185 	 */
186 
187 	m = (110000 - ((p1_ratio - ratio) * 625)) / 11;
188 	m = (m * m) / 1000;
189 
190 	power = ((ratio * 100000 / p1_ratio) / 100);
191 	power *= (m / 100) * (tdp / 1000);
192 	power /= 1000;
193 
194 	return power;
195 }
196 
generate_c_state_entries(void)197 static void generate_c_state_entries(void)
198 {
199 	const acpi_cstate_t *c_state_map;
200 	size_t entries;
201 
202 	c_state_map = soc_get_cstate_map(&entries);
203 
204 	/* Generate C-state tables */
205 	acpigen_write_CST_package(c_state_map, entries);
206 }
207 
generate_p_state_entries(int core,int cores_per_package)208 void generate_p_state_entries(int core, int cores_per_package)
209 {
210 	int ratio_min, ratio_max, ratio_turbo, ratio_step;
211 	int coord_type, power_max, num_entries;
212 	int ratio, power, clock, clock_max;
213 	bool turbo;
214 
215 	coord_type = cpu_get_coord_type();
216 	ratio_min = cpu_get_min_ratio();
217 	ratio_max = cpu_get_max_ratio();
218 	clock_max = (ratio_max * cpu_get_bus_clock()) / KHz;
219 	turbo = (get_turbo_state() == TURBO_ENABLED);
220 
221 	/* Calculate CPU TDP in mW */
222 	power_max = cpu_get_power_max();
223 
224 	/* Write _PCT indicating use of FFixedHW */
225 	acpigen_write_empty_PCT();
226 
227 	/* Write _PPC with no limit on supported P-state */
228 	acpigen_write_PPC_NVS();
229 	/* Write PSD indicating configured coordination type */
230 	acpigen_write_PSD_package(core, 1, coord_type);
231 
232 	/* Add P-state entries in _PSS table */
233 	acpigen_write_name("_PSS");
234 
235 	/* Determine ratio points */
236 	ratio_step = PSS_RATIO_STEP;
237 	do {
238 		num_entries = ((ratio_max - ratio_min) / ratio_step) + 1;
239 		if (((ratio_max - ratio_min) % ratio_step) > 0)
240 			num_entries += 1;
241 		if (turbo)
242 			num_entries += 1;
243 		if (num_entries > PSS_MAX_ENTRIES)
244 			ratio_step += 1;
245 	} while (num_entries > PSS_MAX_ENTRIES);
246 
247 	/* _PSS package count depends on Turbo */
248 	acpigen_write_package(num_entries);
249 
250 	/* P[T] is Turbo state if enabled */
251 	if (turbo) {
252 		ratio_turbo = cpu_get_max_turbo_ratio();
253 
254 		/* Add entry for Turbo ratio */
255 		acpigen_write_PSS_package(clock_max + 1,	/* MHz */
256 					  power_max,		/* mW */
257 					  PSS_LATENCY_TRANSITION,/* lat1 */
258 					  PSS_LATENCY_BUSMASTER,/* lat2 */
259 					  ratio_turbo << 8,	/* control */
260 					  ratio_turbo << 8);	/* status */
261 		num_entries -= 1;
262 	}
263 
264 	/* First regular entry is max non-turbo ratio */
265 	acpigen_write_PSS_package(clock_max,		/* MHz */
266 				  power_max,		/* mW */
267 				  PSS_LATENCY_TRANSITION,/* lat1 */
268 				  PSS_LATENCY_BUSMASTER,/* lat2 */
269 				  ratio_max << 8,	/* control */
270 				  ratio_max << 8);	/* status */
271 	num_entries -= 1;
272 
273 	/* Generate the remaining entries */
274 	for (ratio = ratio_min + ((num_entries - 1) * ratio_step);
275 	     ratio >= ratio_min; ratio -= ratio_step) {
276 		/* Calculate power at this ratio */
277 		power = common_calculate_power_ratio(power_max, ratio_max, ratio);
278 		clock = (ratio * cpu_get_bus_clock()) / KHz;
279 
280 		acpigen_write_PSS_package(clock,		/* MHz */
281 					  power,		/* mW */
282 					  PSS_LATENCY_TRANSITION,/* lat1 */
283 					  PSS_LATENCY_BUSMASTER,/* lat2 */
284 					  ratio << 8,		/* control */
285 					  ratio << 8);		/* status */
286 	}
287 	/* Fix package length */
288 	acpigen_pop_len();
289 }
290 
soc_get_tss_table(int * entries)291 __weak acpi_tstate_t *soc_get_tss_table(int *entries)
292 {
293 	*entries = 0;
294 	return NULL;
295 }
296 
generate_t_state_entries(int core,int cores_per_package)297 void generate_t_state_entries(int core, int cores_per_package)
298 {
299 	acpi_tstate_t *soc_tss_table;
300 	int entries;
301 
302 	soc_tss_table = soc_get_tss_table(&entries);
303 	if (entries == 0)
304 		return;
305 
306 	/* Indicate SW_ALL coordination for T-states */
307 	acpigen_write_TSD_package(core, cores_per_package, SW_ALL);
308 
309 	/* Indicate FixedHW so OS will use MSR */
310 	acpigen_write_empty_PTC();
311 
312 	/* Set NVS controlled T-state limit */
313 	acpigen_write_TPC("\\TLVL");
314 
315 	/* Write TSS table for MSR access */
316 	acpigen_write_TSS_package(entries, soc_tss_table);
317 }
318 
generate_cppc_entries(int core_id)319 static void generate_cppc_entries(int core_id)
320 {
321 	u32 version = CPPC_VERSION_2;
322 
323 	if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID))
324 		version = CPPC_VERSION_3;
325 
326 	if (!(CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPPC) &&
327 	      cpuid_eax(6) & CPUID_6_EAX_ISST))
328 		return;
329 
330 	/* Generate GCPC package in first logical core */
331 	if (core_id == 0) {
332 		struct cppc_config cppc_config;
333 		cpu_init_cppc_config(&cppc_config, version);
334 		acpigen_write_CPPC_package(&cppc_config);
335 	}
336 
337 	/* Write _CPC entry for each logical core */
338 	if (CONFIG(SOC_INTEL_COMMON_BLOCK_ACPI_CPU_HYBRID))
339 		acpigen_write_CPPC_hybrid_method(core_id);
340 	else
341 		acpigen_write_CPPC_method();
342 }
343 
soc_power_states_generation(int core_id,int cores_per_package)344 __weak void soc_power_states_generation(int core_id,
345 						int cores_per_package)
346 {
347 }
348 
generate_cpu_entry(int cpu,int core,int cores_per_package)349 static void generate_cpu_entry(int cpu, int core, int cores_per_package)
350 {
351 	/* Generate processor \_SB.CPUx */
352 	acpigen_write_processor_device(cpu * cores_per_package + core);
353 
354 	/* Generate C-state tables */
355 	generate_c_state_entries();
356 
357 	generate_cppc_entries(core);
358 
359 	/* Soc specific power states generation */
360 	soc_power_states_generation(core, cores_per_package);
361 
362 	acpigen_write_processor_device_end();
363 }
364 
generate_cpu_entries(const struct device * device)365 void generate_cpu_entries(const struct device *device)
366 {
367 	int core_id, cpu_id;
368 	int totalcores = dev_count_cpu();
369 	unsigned int num_virt;
370 	unsigned int num_phys;
371 
372 	cpu_read_topology(&num_phys, &num_virt);
373 
374 	int numcpus = totalcores / num_virt;
375 
376 	printk(BIOS_DEBUG, "Found %d CPU(s) with %d/%d physical/logical core(s) each.\n",
377 	       numcpus, num_phys, num_virt);
378 
379 	for (cpu_id = 0; cpu_id < numcpus; cpu_id++)
380 		for (core_id = 0; core_id < num_virt; core_id++)
381 			generate_cpu_entry(cpu_id, core_id, num_virt);
382 
383 	/* PPKG is usually used for thermal management
384 	   of the first and only package. */
385 	acpigen_write_processor_package("PPKG", 0, num_virt);
386 
387 	/* Add a method to notify processor nodes */
388 	acpigen_write_processor_cnot(num_virt);
389 
390 	if (CONFIG(SOC_INTEL_COMMON_BLOCK_SGX_ENABLE))
391 		sgx_fill_ssdt();
392 }
393 
394 
fill_wdat_timeout_entry(acpi_wdat_entry_t * entry)395 static bool fill_wdat_timeout_entry(acpi_wdat_entry_t *entry)
396 {
397 	uint16_t tcobase = tco_get_bar();
398 
399 	if (tcobase == 0)
400 		return false;
401 
402 	memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
403 
404 	entry->action = ACPI_WDAT_SET_COUNTDOWN;
405 	entry->instruction = ACPI_WDAT_WRITE_COUNTDOWN | ACPI_WDAT_PRESERVE_REGISTER;
406 	entry->mask = TCO_TMR_MASK;
407 	entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
408 	entry->register_region.addrl = tcobase + TCO_TMR;
409 	entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_WORD;
410 
411 	return true;
412 }
413 
fill_wdat_boot_status_entry(acpi_wdat_entry_t * entry,uint8_t action,uint8_t instruction,uint32_t value)414 static bool fill_wdat_boot_status_entry(acpi_wdat_entry_t *entry, uint8_t action,
415 					uint8_t instruction, uint32_t value)
416 {
417 	uint16_t tcobase = tco_get_bar();
418 
419 	if (tcobase == 0)
420 		return false;
421 
422 	memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
423 
424 	entry->action = action;
425 	entry->instruction = instruction;
426 	entry->value = value;
427 	entry->mask = TCO2_STS_SECOND_TO;
428 	entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
429 	entry->register_region.addrl = tcobase + TCO_MESSAGE1;
430 	entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_BYTE;
431 
432 	return true;
433 }
434 
fill_wdat_run_state_entry(acpi_wdat_entry_t * entry,uint8_t action,uint8_t instruction,uint32_t value)435 static bool fill_wdat_run_state_entry(acpi_wdat_entry_t *entry, uint8_t action,
436 				       uint8_t instruction, uint32_t value)
437 {
438 	uint16_t tcobase = tco_get_bar();
439 
440 	if (tcobase == 0)
441 		return false;
442 
443 	memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
444 
445 	entry->action = action;
446 	entry->instruction = instruction;
447 	entry->value = value;
448 	entry->mask = TCO1_TMR_HLT;
449 	entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
450 	entry->register_region.addrl = tcobase + TCO1_CNT;
451 	entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_WORD;
452 
453 	return true;
454 }
455 
fill_wdat_ping_entry(acpi_wdat_entry_t * entry)456 static bool fill_wdat_ping_entry(acpi_wdat_entry_t *entry)
457 {
458 	uint16_t tcobase = tco_get_bar();
459 
460 	if (tcobase == 0)
461 		return false;
462 
463 	memset((void *)entry, 0, sizeof(acpi_wdat_entry_t));
464 
465 	entry->action = ACPI_WDAT_RESET;
466 	entry->instruction = ACPI_WDAT_WRITE_VALUE;
467 	entry->value = 0x01;
468 	entry->mask = 0x01;
469 	entry->register_region.space_id = ACPI_ADDRESS_SPACE_IO;
470 	entry->register_region.addrl = tcobase + TCO_RLD;
471 	entry->register_region.access_size = ACPI_WDAT_ACCESS_SIZE_WORD;
472 
473 	return true;
474 }
475 
acpi_soc_fill_wdat(acpi_wdat_t * wdat,unsigned long current)476 unsigned long acpi_soc_fill_wdat(acpi_wdat_t *wdat, unsigned long current)
477 {
478 	if (!wdat)
479 		return current;
480 
481 	uint16_t tcobase = tco_get_bar();
482 
483 	if (tcobase == 0)
484 		goto out_err;
485 
486 	wdat->pci_segment = 0xff;
487 	wdat->pci_bus = 0xff;
488 	wdat->pci_device = 0xff;
489 	wdat->pci_function = 0xff;
490 
491 	wdat->timer_period = tco_get_timer_period();
492 	wdat->min_count = tco_get_timer_min_value();
493 	wdat->max_count = tco_get_timer_max_value();
494 	wdat->flags = ACPI_WDAT_FLAG_ENABLED;
495 	wdat->entries = 0;
496 
497 	acpi_wdat_entry_t *entry = (acpi_wdat_entry_t *)current;
498 
499 	/* Write countdown */
500 	if (!fill_wdat_timeout_entry(entry))
501 		goto out_err;
502 
503 	entry++;
504 
505 	/* Get boot status */
506 	if (!fill_wdat_boot_status_entry(entry, ACPI_WDAT_GET_STATUS,
507 					 ACPI_WDAT_READ_VALUE, TCO2_STS_SECOND_TO))
508 		goto out_err;
509 
510 	entry++;
511 
512 	/* Set boot status */
513 	if (!fill_wdat_boot_status_entry(entry, ACPI_WDAT_SET_STATUS,
514 					 ACPI_WDAT_WRITE_VALUE | ACPI_WDAT_PRESERVE_REGISTER,
515 					 0))
516 		goto out_err;
517 
518 	entry++;
519 
520 	/* Get running status */
521 	if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_GET_RUNNING_STATE,
522 				       ACPI_WDAT_READ_VALUE, 0))
523 		goto out_err;
524 
525 	entry++;
526 
527 	/* Start the watchdog */
528 	if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_SET_RUNNING_STATE,
529 				       ACPI_WDAT_WRITE_VALUE | ACPI_WDAT_PRESERVE_REGISTER,
530 				       0))
531 		goto out_err;
532 
533 	entry++;
534 
535 	/* Get stopped status */
536 	if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_GET_STOPPED_STATE,
537 				       ACPI_WDAT_READ_VALUE, TCO1_TMR_HLT))
538 		goto out_err;
539 
540 	entry++;
541 
542 	/* Stop the watchdog */
543 	if (!fill_wdat_run_state_entry(entry, ACPI_WDAT_SET_STOPPED_STATE,
544 				       ACPI_WDAT_WRITE_VALUE | ACPI_WDAT_PRESERVE_REGISTER,
545 				       TCO1_TMR_HLT))
546 		goto out_err;
547 
548 	entry++;
549 
550 	/* Ping */
551 	if (!fill_wdat_ping_entry(entry))
552 		goto out_err;
553 
554 	entry++;
555 
556 	wdat->entries = ((unsigned long)entry - current) / sizeof(acpi_wdat_entry_t);
557 
558 	return (unsigned long)entry;
559 
560 out_err:
561 	wdat->flags = ACPI_WDAT_FLAG_DISABLED;
562 	printk(BIOS_ERR, "Fail to populate WDAT ACPI Table");
563 
564 	return current;
565 }
566