Stefan Reinauer (stefan.reinauer@coreboot.org) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/2817
-gerrit
commit 210d4c7d5d67cb040bb3adfd7f47f96468659464 Author: Duncan Laurie dlaurie@chromium.org Date: Fri Mar 8 17:16:37 2013 -0800
lynxpoint: Fix ELOG logging of power management events
This is updated to handle LynxPoint-H and LynxPoint-LP and a new wake event is added for the power button.
Boot, suspend/resume, reboot, etc on WTM2 and then check the event log to see if expected events have been added.
Change-Id: I15cbc3901d81f4fd77cc04de37ff5fa048f9d3e8 Signed-off-by: Duncan Laurie dlaurie@chromium.org --- src/include/elog.h | 1 + src/southbridge/intel/lynxpoint/elog.c | 119 ++++++++++++++++++++++++++------- 2 files changed, 97 insertions(+), 23 deletions(-)
diff --git a/src/include/elog.h b/src/include/elog.h index a5b5a77..a65893c 100644 --- a/src/include/elog.h +++ b/src/include/elog.h @@ -113,6 +113,7 @@ #define ELOG_WAKE_SOURCE_RTC 0x03 #define ELOG_WAKE_SOURCE_GPIO 0x04 #define ELOG_WAKE_SOURCE_SMBUS 0x05 +#define ELOG_WAKE_SOURCE_PWRBTN 0x06 struct elog_event_data_wake { u8 source; u32 instance; diff --git a/src/southbridge/intel/lynxpoint/elog.c b/src/southbridge/intel/lynxpoint/elog.c index 09dfcdb..9ba3a98 100644 --- a/src/southbridge/intel/lynxpoint/elog.c +++ b/src/southbridge/intel/lynxpoint/elog.c @@ -28,20 +28,101 @@ #include <elog.h> #include "pch.h"
+static void pch_log_standard_gpe(u32 gpe0_sts_reg, u32 gpe0_en_reg) +{ + u32 gpe0_en = inl(get_pmbase() + gpe0_en_reg); + u32 gpe0_sts = inl(get_pmbase() + gpe0_sts_reg) & gpe0_en; + + /* PME (TODO: determine wake device) */ + if (gpe0_sts & (1 << 11)) + elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0); + + /* Internal PME (TODO: determine wake device) */ + if (gpe0_sts & (1 << 13)) + elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0); + + /* SMBUS Wake */ + if (gpe0_sts & (1 << 7)) + elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0); +} + +static void pch_log_gpio_gpe(u32 gpe0_sts_reg, u32 gpe0_en_reg, int start) +{ + /* GPE Bank 1 is GPIO 0-31 */ + u32 gpe0_en = inl(get_pmbase() + gpe0_en_reg); + u32 gpe0_sts = inl(get_pmbase() + gpe0_sts_reg) & gpe0_en; + int i; + + for (i = 0; i <= 31; i++) { + if (gpe0_sts & (1 << i)) + elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i + start); + } +} + +static void pch_log_gpe(void) +{ + int i; + u16 pmbase = get_pmbase(); + u32 gpe0_sts, gpe0_en; + int gpe0_high_gpios[] = { + [0] = 27, + [24] = 17, + [25] = 19, + [26] = 21, + [27] = 22, + [28] = 43, + [29] = 56, + [30] = 57, + [31] = 60 + }; + + pch_log_standard_gpe(GPE0_EN, GPE0_STS); + + /* GPIO 0-15 */ + gpe0_en = inw(pmbase + GPE0_EN + 2); + gpe0_sts = inw(pmbase + GPE0_STS + 2) & gpe0_en; + for (i = 0; i <= 15; i++) { + if (gpe0_sts & (1 << i)) + elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i); + } + + /* + * Now check and log upper status bits + */ + + gpe0_en = inl(pmbase + GPE0_EN_2); + gpe0_sts = inl(pmbase + GPE0_STS_2) & gpe0_en; + + for (i = 0; i <= 31; i++) { + if (!gpe0_high_gpios[i]) + continue; + if (gpe0_sts & (1 << i)) + elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, + gpe0_high_gpios[i]); + } +} + +static void pch_lp_log_gpe(void) +{ + /* Standard GPE are in GPE set 4 */ + pch_log_standard_gpe(LP_GPE0_STS_4, LP_GPE0_EN_4); + + /* Log GPIO events in set 1-3 */ + pch_log_gpio_gpe(LP_GPE0_STS_1, LP_GPE0_EN_1, 0); + pch_log_gpio_gpe(LP_GPE0_STS_2, LP_GPE0_EN_2, 32); + pch_log_gpio_gpe(LP_GPE0_STS_3, LP_GPE0_EN_3, 64); +} + void pch_log_state(void) { u16 pm1_sts, gen_pmcon_3, tco2_sts; - u32 gpe0_sts, gpe0_en; u8 gen_pmcon_2; - int i; struct device *lpc = dev_find_slot(0, PCI_DEVFN(0x1f, 0)); if (!lpc) return;
- pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); - gpe0_sts = inl(DEFAULT_PMBASE + GPE0_STS); - gpe0_en = inl(DEFAULT_PMBASE + GPE0_EN); - tco2_sts = inw(DEFAULT_PMBASE + TCO2_STS); + pm1_sts = inw(get_pmbase() + PM1_STS); + tco2_sts = inw(get_pmbase() + TCO2_STS); gen_pmcon_2 = pci_read_config8(lpc, GEN_PMCON_2); gen_pmcon_3 = pci_read_config16(lpc, GEN_PMCON_3);
@@ -86,6 +167,10 @@ void pch_log_state(void) * Wake sources */
+ /* Power Button */ + if (pm1_sts & (1 << 8)) + elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0); + /* RTC */ if (pm1_sts & (1 << 10)) elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0); @@ -94,21 +179,9 @@ void pch_log_state(void) if (pm1_sts & (1 << 14)) elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
- /* PME (TODO: determine wake device) */ - if (gpe0_sts & (1 << 13)) - elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0); - - /* Internal PME (TODO: determine wake device) */ - if (gpe0_sts & (1 << 13)) - elog_add_event_wake(ELOG_WAKE_SOURCE_PME_INTERNAL, 0); - - /* GPIO 0-15 */ - for (i = 0; i < 16; i++) { - if ((gpe0_sts & (1 << (16+i))) && (gpe0_en & (1 << (16+i)))) - elog_add_event_wake(ELOG_WAKE_SOURCE_GPIO, i); - } - - /* SMBUS Wake */ - if (gpe0_sts & (1 << 7)) - elog_add_event_wake(ELOG_WAKE_SOURCE_SMBUS, 0); + /* GPE */ + if (pch_is_lp()) + pch_lp_log_gpe(); + else + pch_log_gpe(); }