xref: /aosp_15_r20/external/coreboot/src/soc/amd/common/block/acpi/acpi.c (revision b9411a12aaaa7e1e6a6fb7c5e057f44ee179a49c)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <acpi/acpi.h>
4 #include <acpi/acpi_pm.h>
5 #include <amdblocks/acpimmio.h>
6 #include <amdblocks/acpi.h>
7 #include <bootmode.h>
8 #include <console/console.h>
9 #include <halt.h>
10 #include <security/vboot/vboot_common.h>
11 #include <soc/southbridge.h>
12 
poweroff(void)13 void poweroff(void)
14 {
15 	acpi_write32(MMIO_ACPI_PM1_CNT_BLK,
16 			  (SLP_TYP_S5 << SLP_TYP_SHIFT) | SLP_EN);
17 
18 	/*
19 	 * Setting SLP_TYP_S5 in PM1 triggers SLP_SMI, which is handled by SMM
20 	 * to transition to S5 state. If halt is called in SMM, then it prevents
21 	 * the SMI handler from being triggered and system never enters S5.
22 	 */
23 	if (!ENV_SMM)
24 		halt();
25 }
26 
print_num_status_bits(int num_bits,uint32_t status,const char * const bit_names[])27 static void print_num_status_bits(int num_bits, uint32_t status,
28 				  const char *const bit_names[])
29 {
30 	int i;
31 
32 	if (!status)
33 		return;
34 
35 	for (i = num_bits - 1; i >= 0; i--) {
36 		if (status & (1 << i)) {
37 			if (bit_names[i])
38 				printk(BIOS_DEBUG, "%s ", bit_names[i]);
39 			else
40 				printk(BIOS_DEBUG, "BIT%d ", i);
41 		}
42 	}
43 }
44 
print_pm1_status(uint16_t pm1_sts)45 static uint16_t print_pm1_status(uint16_t pm1_sts)
46 {
47 	static const char *const pm1_sts_bits[16] = {
48 		[0] = "TMROF",
49 		[4] = "BMSTATUS",
50 		[5] = "GBL",
51 		[8] = "PWRBTN",
52 		[10] = "RTC",
53 		[14] = "PCIEXPWAK",
54 		[15] = "WAK",
55 	};
56 
57 	if (!pm1_sts)
58 		return 0;
59 
60 	printk(BIOS_DEBUG, "PM1_STS: ");
61 	print_num_status_bits(ARRAY_SIZE(pm1_sts_bits), pm1_sts, pm1_sts_bits);
62 	printk(BIOS_DEBUG, "\n");
63 
64 	return pm1_sts;
65 }
66 
acpi_fill_pm_gpe_state(struct acpi_pm_gpe_state * state)67 void acpi_fill_pm_gpe_state(struct acpi_pm_gpe_state *state)
68 {
69 	state->pm1_sts = acpi_read16(MMIO_ACPI_PM1_STS);
70 	state->pm1_en = acpi_read16(MMIO_ACPI_PM1_EN);
71 	state->gpe0_sts = acpi_read32(MMIO_ACPI_GPE0_STS);
72 	state->gpe0_en = acpi_read32(MMIO_ACPI_GPE0_EN);
73 	state->previous_sx_state = acpi_get_sleep_type();
74 	state->aligning_field = 0;
75 }
76 
acpi_pm_gpe_add_events_print_events(void)77 void acpi_pm_gpe_add_events_print_events(void)
78 {
79 	const struct chipset_power_state *ps;
80 	const struct acpi_pm_gpe_state *state;
81 
82 	if (acpi_fetch_pm_state(&ps, PS_CLAIMER_ELOG) < 0)
83 		return;
84 
85 	state = &ps->gpe_state;
86 	print_pm1_status(state->pm1_sts);
87 	acpi_log_events(ps);
88 }
89 
acpi_clear_pm_gpe_status(void)90 void acpi_clear_pm_gpe_status(void)
91 {
92 	acpi_write16(MMIO_ACPI_PM1_STS, acpi_read16(MMIO_ACPI_PM1_STS));
93 	acpi_write32(MMIO_ACPI_GPE0_STS, acpi_read32(MMIO_ACPI_GPE0_STS));
94 }
95 
acpi_get_sleep_type(void)96 int acpi_get_sleep_type(void)
97 {
98 	return acpi_sleep_from_pm1(acpi_read16(MMIO_ACPI_PM1_CNT_BLK));
99 }
100 
platform_is_resuming(void)101 int platform_is_resuming(void)
102 {
103 	if (!(acpi_read16(MMIO_ACPI_PM1_STS) & WAK_STS))
104 		return 0;
105 
106 	return acpi_get_sleep_type() == ACPI_S3;
107 }
108 
109 /* If a system reset is about to be requested, modify the PM1 register so it
110  * will never be misinterpreted as an S3 resume. */
set_pm1cnt_s5(void)111 void set_pm1cnt_s5(void)
112 {
113 	uint16_t pm1;
114 
115 	pm1 = acpi_read16(MMIO_ACPI_PM1_CNT_BLK);
116 	pm1 &= ~SLP_TYP;
117 	pm1 |= SLP_TYP_S5 << SLP_TYP_SHIFT;
118 	acpi_write16(MMIO_ACPI_PM1_CNT_BLK, pm1);
119 }
120 
vboot_platform_prepare_reboot(void)121 void vboot_platform_prepare_reboot(void)
122 {
123 	set_pm1cnt_s5();
124 }
125 
acpi_enable_sci(void)126 void acpi_enable_sci(void)
127 {
128 	uint32_t pm1;
129 
130 	pm1 = acpi_read32(MMIO_ACPI_PM1_CNT_BLK);
131 	pm1 |= ACPI_PM1_CNT_SCIEN;
132 	acpi_write32(MMIO_ACPI_PM1_CNT_BLK, pm1);
133 }
134 
acpi_disable_sci(void)135 void acpi_disable_sci(void)
136 {
137 	uint32_t pm1;
138 
139 	pm1 = acpi_read32(MMIO_ACPI_PM1_CNT_BLK);
140 	pm1 &= ~ACPI_PM1_CNT_SCIEN;
141 	acpi_write32(MMIO_ACPI_PM1_CNT_BLK, pm1);
142 }
143