blob: 75d4adf8114e18853711e380e63f4424b006664c [file] [log] [blame]
Angel Ponsae593872020-04-04 18:50:57 +02001/* SPDX-License-Identifier: GPL-2.0-only */
Chris Ching044dfe92018-01-03 16:26:36 -07002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Kyösti Mälkkib0db8132021-01-21 16:34:43 +02004#include <acpi/acpi_pm.h>
Karthikeyan Ramasubramanian589ac692021-07-15 14:58:23 -06005#include <amdblocks/acpimmio.h>
6#include <amdblocks/acpi.h>
Bill XIE516c0a52020-02-24 23:08:35 +08007#include <bootmode.h>
Bill XIE516c0a52020-02-24 23:08:35 +08008#include <console/console.h>
Chris Ching044dfe92018-01-03 16:26:36 -07009#include <halt.h>
Marshall Dawson4ee83b22019-05-03 11:44:22 -060010#include <security/vboot/vboot_common.h>
Bill XIE516c0a52020-02-24 23:08:35 +080011#include <soc/southbridge.h>
Chris Ching044dfe92018-01-03 16:26:36 -070012
13void poweroff(void)
14{
Richard Spiegele24d7952018-10-26 13:25:01 -070015 acpi_write32(MMIO_ACPI_PM1_CNT_BLK,
16 (SLP_TYP_S5 << SLP_TYP_SHIFT) | SLP_EN);
Raul E Rangel06bc4d72018-05-25 16:11:39 -060017
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();
Chris Ching044dfe92018-01-03 16:26:36 -070025}
Marshall Dawson4ee83b22019-05-03 11:44:22 -060026
Marshall Dawson4ee83b22019-05-03 11:44:22 -060027static 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
45static 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
Aaron Durbin746e5982020-08-14 14:48:45 -060067void 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
Kyösti Mälkkib0db8132021-01-21 16:34:43 +020077void acpi_pm_gpe_add_events_print_events(void)
Aaron Durbin746e5982020-08-14 14:48:45 -060078{
Kyösti Mälkkib0db8132021-01-21 16:34:43 +020079 const struct chipset_power_state *ps;
80 const struct acpi_pm_gpe_state *state;
81
Fabio Aiutofdcf6982022-09-11 12:25:13 +020082 if (acpi_fetch_pm_state(&ps, PS_CLAIMER_ELOG) < 0)
Kyösti Mälkkib0db8132021-01-21 16:34:43 +020083 return;
84
85 state = &ps->gpe_state;
Aaron Durbin746e5982020-08-14 14:48:45 -060086 print_pm1_status(state->pm1_sts);
Karthikeyan Ramasubramanian589ac692021-07-15 14:58:23 -060087 acpi_log_events(ps);
Aaron Durbin746e5982020-08-14 14:48:45 -060088}
89
90void 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
Marshall Dawson26307c72019-05-03 13:06:55 -060096int acpi_get_sleep_type(void)
97{
98 return acpi_sleep_from_pm1(acpi_read16(MMIO_ACPI_PM1_CNT_BLK));
99}
100
Bill XIE516c0a52020-02-24 23:08:35 +0800101int platform_is_resuming(void)
Marshall Dawson4ee83b22019-05-03 11:44:22 -0600102{
103 if (!(acpi_read16(MMIO_ACPI_PM1_STS) & WAK_STS))
104 return 0;
105
Marshall Dawson26307c72019-05-03 13:06:55 -0600106 return acpi_get_sleep_type() == ACPI_S3;
Marshall Dawson4ee83b22019-05-03 11:44:22 -0600107}
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. */
111void 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
121void vboot_platform_prepare_reboot(void)
122{
123 set_pm1cnt_s5();
124}
125
126void 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
135void 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}