Angel Pons | 182dbde | 2020-04-02 23:49:05 +0200 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 2 | |
| 3 | #include <arch/io.h> |
Furquan Shaikh | 76cedd2 | 2020-05-02 10:24:23 -0700 | [diff] [blame] | 4 | #include <acpi/acpi.h> |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 5 | #include <device/device.h> |
| 6 | #include <device/pci.h> |
| 7 | #include <device/pci_ops.h> |
| 8 | #include <stdint.h> |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 9 | #include <elog.h> |
| 10 | #include "pch.h" |
| 11 | |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 12 | static void pch_log_standard_gpe(u32 gpe0_sts_reg, u32 gpe0_en_reg) |
| 13 | { |
| 14 | u32 gpe0_en = inl(get_pmbase() + gpe0_en_reg); |
| 15 | u32 gpe0_sts = inl(get_pmbase() + gpe0_sts_reg) & gpe0_en; |
| 16 | |
| 17 | /* PME (TODO: determine wake device) */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 18 | if (gpe0_sts & PME_STS) |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 19 | elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0); |
| 20 | |
| 21 | /* Internal PME (TODO: determine wake device) */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 22 | if (gpe0_sts & PME_B0_STS) |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 23 | elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0); |
| 24 | |
| 25 | /* SMBUS Wake */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 26 | if (gpe0_sts & SMB_WAK_STS) |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 27 | elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0); |
| 28 | } |
| 29 | |
| 30 | static void pch_log_gpio_gpe(u32 gpe0_sts_reg, u32 gpe0_en_reg, int start) |
| 31 | { |
| 32 | /* GPE Bank 1 is GPIO 0-31 */ |
| 33 | u32 gpe0_en = inl(get_pmbase() + gpe0_en_reg); |
| 34 | u32 gpe0_sts = inl(get_pmbase() + gpe0_sts_reg) & gpe0_en; |
| 35 | int i; |
| 36 | |
| 37 | for (i = 0; i <= 31; i++) { |
| 38 | if (gpe0_sts & (1 << i)) |
Aaron Durbin | aa90203 | 2020-08-17 09:37:13 -0600 | [diff] [blame] | 39 | elog_add_event_wake(ELOG_WAKE_SOURCE_GPE, i + start); |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 40 | } |
| 41 | } |
| 42 | |
| 43 | static void pch_log_gpe(void) |
| 44 | { |
| 45 | int i; |
| 46 | u16 pmbase = get_pmbase(); |
| 47 | u32 gpe0_sts, gpe0_en; |
| 48 | int gpe0_high_gpios[] = { |
Angel Pons | 2aaf7c0 | 2020-09-24 18:03:18 +0200 | [diff] [blame] | 49 | [0] = 27, |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 50 | [24] = 17, |
| 51 | [25] = 19, |
| 52 | [26] = 21, |
| 53 | [27] = 22, |
| 54 | [28] = 43, |
| 55 | [29] = 56, |
| 56 | [30] = 57, |
| 57 | [31] = 60 |
| 58 | }; |
| 59 | |
| 60 | pch_log_standard_gpe(GPE0_EN, GPE0_STS); |
| 61 | |
| 62 | /* GPIO 0-15 */ |
Kyösti Mälkki | ab368d9 | 2023-05-06 14:37:22 +0300 | [diff] [blame^] | 63 | gpe0_en = inw(pmbase + GPE0_EN + sizeof(uint16_t)); |
| 64 | gpe0_sts = inw(pmbase + GPE0_STS + sizeof(uint16_t)) & gpe0_en; |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 65 | for (i = 0; i <= 15; i++) { |
| 66 | if (gpe0_sts & (1 << i)) |
Aaron Durbin | aa90203 | 2020-08-17 09:37:13 -0600 | [diff] [blame] | 67 | elog_add_event_wake(ELOG_WAKE_SOURCE_GPE, i); |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 68 | } |
| 69 | |
| 70 | /* |
| 71 | * Now check and log upper status bits |
| 72 | */ |
| 73 | |
Kyösti Mälkki | ab368d9 | 2023-05-06 14:37:22 +0300 | [diff] [blame^] | 74 | gpe0_en = inl(pmbase + GPE0_EN + sizeof(uint32_t)); |
| 75 | gpe0_sts = inl(pmbase + GPE0_STS + sizeof(uint32_t)) & gpe0_en; |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 76 | |
| 77 | for (i = 0; i <= 31; i++) { |
| 78 | if (!gpe0_high_gpios[i]) |
| 79 | continue; |
| 80 | if (gpe0_sts & (1 << i)) |
Aaron Durbin | aa90203 | 2020-08-17 09:37:13 -0600 | [diff] [blame] | 81 | elog_add_event_wake(ELOG_WAKE_SOURCE_GPE, |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 82 | gpe0_high_gpios[i]); |
| 83 | } |
| 84 | } |
| 85 | |
| 86 | static void pch_lp_log_gpe(void) |
| 87 | { |
| 88 | /* Standard GPE are in GPE set 4 */ |
| 89 | pch_log_standard_gpe(LP_GPE0_STS_4, LP_GPE0_EN_4); |
| 90 | |
| 91 | /* Log GPIO events in set 1-3 */ |
| 92 | pch_log_gpio_gpe(LP_GPE0_STS_1, LP_GPE0_EN_1, 0); |
| 93 | pch_log_gpio_gpe(LP_GPE0_STS_2, LP_GPE0_EN_2, 32); |
| 94 | pch_log_gpio_gpe(LP_GPE0_STS_3, LP_GPE0_EN_3, 64); |
| 95 | } |
| 96 | |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 97 | void pch_log_state(void) |
| 98 | { |
| 99 | u16 pm1_sts, gen_pmcon_3, tco2_sts; |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 100 | u8 gen_pmcon_2; |
Kyösti Mälkki | c70eed1 | 2018-05-22 02:18:00 +0300 | [diff] [blame] | 101 | struct device *lpc = pcidev_on_root(0x1f, 0); |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 102 | if (!lpc) |
| 103 | return; |
| 104 | |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 105 | pm1_sts = inw(get_pmbase() + PM1_STS); |
| 106 | tco2_sts = inw(get_pmbase() + TCO2_STS); |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 107 | gen_pmcon_2 = pci_read_config8(lpc, GEN_PMCON_2); |
| 108 | gen_pmcon_3 = pci_read_config16(lpc, GEN_PMCON_3); |
| 109 | |
| 110 | /* PWR_FLR Power Failure */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 111 | if (gen_pmcon_2 & PWROK_FLR) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 112 | elog_add_event(ELOG_TYPE_POWER_FAIL); |
| 113 | |
| 114 | /* SUS Well Power Failure */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 115 | if (gen_pmcon_3 & SUS_PWR_FLR) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 116 | elog_add_event(ELOG_TYPE_SUS_POWER_FAIL); |
| 117 | |
| 118 | /* SYS_PWROK Failure */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 119 | if (gen_pmcon_2 & SYSPWR_FLR) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 120 | elog_add_event(ELOG_TYPE_SYS_PWROK_FAIL); |
| 121 | |
| 122 | /* PWROK Failure */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 123 | if (gen_pmcon_2 & PWROK_FLR) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 124 | elog_add_event(ELOG_TYPE_PWROK_FAIL); |
| 125 | |
| 126 | /* Second TCO Timeout */ |
Kyösti Mälkki | 307320c | 2022-11-21 17:27:07 +0200 | [diff] [blame] | 127 | if (tco2_sts & TCO2_STS_SECOND_TO) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 128 | elog_add_event(ELOG_TYPE_TCO_RESET); |
| 129 | |
| 130 | /* Power Button Override */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 131 | if (pm1_sts & PRBTNOR_STS) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 132 | elog_add_event(ELOG_TYPE_POWER_BUTTON_OVERRIDE); |
| 133 | |
| 134 | /* System Reset Status (reset button pushed) */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 135 | if (gen_pmcon_2 & SYSTEM_RESET_STS) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 136 | elog_add_event(ELOG_TYPE_RESET_BUTTON); |
| 137 | |
| 138 | /* General Reset Status */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 139 | if (gen_pmcon_3 & GEN_RST_STS) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 140 | elog_add_event(ELOG_TYPE_SYSTEM_RESET); |
| 141 | |
| 142 | /* ACPI Wake */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 143 | if (pm1_sts & WAK_STS) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 144 | elog_add_event_byte(ELOG_TYPE_ACPI_WAKE, |
Kyösti Mälkki | c3ed886 | 2014-06-19 19:50:51 +0300 | [diff] [blame] | 145 | acpi_is_wakeup_s3() ? 3 : 5); |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 146 | |
| 147 | /* |
| 148 | * Wake sources |
| 149 | */ |
| 150 | |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 151 | /* Power Button */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 152 | if (pm1_sts & PWRBTN_STS) |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 153 | elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0); |
| 154 | |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 155 | /* RTC */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 156 | if (pm1_sts & RTC_STS) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 157 | elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0); |
| 158 | |
| 159 | /* PCI Express (TODO: determine wake device) */ |
Angel Pons | 35605d6 | 2021-04-24 11:54:01 +0200 | [diff] [blame] | 160 | if (pm1_sts & PCIEXPWAK_STS) |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 161 | elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0); |
| 162 | |
Duncan Laurie | d604090 | 2013-03-08 17:16:37 -0800 | [diff] [blame] | 163 | /* GPE */ |
| 164 | if (pch_is_lp()) |
| 165 | pch_lp_log_gpe(); |
| 166 | else |
| 167 | pch_log_gpe(); |
Aaron Durbin | 76c3700 | 2012-10-30 09:03:43 -0500 | [diff] [blame] | 168 | } |