xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/acpi/pm_state.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 <amdblocks/acpi.h>
6 #include <bootstate.h>
7 #include <soc/nvs.h>
8 #include <soc/southbridge.h>
9 #include <types.h>
10 
get_index_bit(uint32_t value,uint16_t limit)11 static int get_index_bit(uint32_t value, uint16_t limit)
12 {
13 	uint16_t i;
14 	uint32_t t;
15 
16 	if (limit > TOTAL_BITS(uint32_t))
17 		return -1;
18 
19 	/* get a mask of valid bits. Ex limit = 3, set bits 0-2 */
20 	t = (1ULL << limit) - 1;
21 	if ((value & t) == 0)
22 		return -1;
23 	t = 1;
24 	for (i = 0; i < limit; i++) {
25 		if (value & t)
26 			break;
27 		t <<= 1;
28 	}
29 	return i;
30 }
31 
pm_fill_gnvs(struct global_nvs * gnvs,const struct acpi_pm_gpe_state * state)32 static void pm_fill_gnvs(struct global_nvs *gnvs, const struct acpi_pm_gpe_state *state)
33 {
34 	int index;
35 
36 	index = get_index_bit(state->pm1_sts & state->pm1_en, PM1_LIMIT);
37 	if (index >= 0)
38 		gnvs->pm1i = index;
39 
40 	index = get_index_bit(state->gpe0_sts & state->gpe0_en, GPE0_LIMIT);
41 	if (index >= 0)
42 		gnvs->gpei = index;
43 }
44 
acpi_save_wake_source(void * unused)45 static void acpi_save_wake_source(void *unused)
46 {
47 	const struct chipset_power_state *ps;
48 	struct global_nvs *gnvs;
49 
50 	if (acpi_reset_gnvs_for_wake(&gnvs) < 0)
51 		return;
52 	if (acpi_fetch_pm_state(&ps, PS_CLAIMER_WAKE) < 0)
53 		return;
54 
55 	pm_fill_gnvs(gnvs, &ps->gpe_state);
56 }
57 
58 BOOT_STATE_INIT_ENTRY(BS_PRE_DEVICE, BS_ON_ENTRY, acpi_save_wake_source, NULL);
59