xref: /aosp_15_r20/external/coreboot/src/soc/intel/common/block/acpi/acpi_wake_source.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi_gnvs.h>
4 #include <acpi/acpi_pm.h>
5 #include <bootstate.h>
6 #include <console/console.h>
7 #include <intelblocks/acpi_wake_source.h>
8 #include <soc/nvs.h>
9 #include <soc/pm.h>
10 #include <stdint.h>
11 
12 /* Save wake source data for ACPI _SWS methods in NVS */
pm_fill_gnvs(struct global_nvs * gnvs,const struct chipset_power_state * ps)13 static void pm_fill_gnvs(struct global_nvs *gnvs, const struct chipset_power_state *ps)
14 {
15 	uint32_t pm1, *gpe0;
16 	int index, gpe_reg, gpe_reg_count;
17 	int reg_size = sizeof(uint32_t) * 8;
18 
19 	gpe_reg_count = soc_fill_acpi_wake(ps, &pm1, &gpe0);
20 	if (gpe_reg_count < 0)
21 		return;
22 
23 	/* Scan for first set bit in PM1 */
24 	for (index = 0; index < reg_size; index++) {
25 		if (pm1 & 1)
26 			break;
27 		pm1 >>= 1;
28 	}
29 
30 	if (index < 16)
31 		gnvs->pm1i = index;
32 
33 	/* Scan for first set bit in GPE registers */
34 	for (gpe_reg = 0; gpe_reg < gpe_reg_count; gpe_reg++) {
35 		uint32_t gpe = gpe0[gpe_reg];
36 		int start = gpe_reg * reg_size;
37 		int end = start + reg_size;
38 
39 		for (index = start; index < end; index++) {
40 			if (gpe & 1)
41 				break;
42 			gpe >>= 1;
43 		}
44 	}
45 
46 	if (index < gpe_reg_count * reg_size)
47 		gnvs->gpei = index;
48 }
49 
acpi_save_wake_source(void * unused)50 static void acpi_save_wake_source(void *unused)
51 {
52 	const struct chipset_power_state *ps;
53 	struct global_nvs *gnvs;
54 
55 	if (acpi_reset_gnvs_for_wake(&gnvs) < 0)
56 		return;
57 	if (acpi_fetch_pm_state(&ps, PS_CLAIMER_WAKE) < 0)
58 		return;
59 
60 	pm_fill_gnvs(gnvs, ps);
61 
62 	printk(BIOS_DEBUG, "ACPI _SWS is PM1 Index %lld GPE Index %lld\n",
63 	       (long long)gnvs->pm1i, (long long)gnvs->gpei);
64 }
65 
66 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, acpi_save_wake_source, NULL);
67