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>
Reviewed-on: http://review.coreboot.org/2817
Tested-by: build bot (Jenkins)
Reviewed-by: Ronald G. Minnich <rminnich@gmail.com>
This commit is contained in:
Duncan Laurie 2013-03-08 17:16:37 -08:00 committed by Ronald G. Minnich
parent 467f31de92
commit d604090b28
2 changed files with 97 additions and 23 deletions

View File

@ -113,6 +113,7 @@
#define ELOG_WAKE_SOURCE_RTC 0x03 #define ELOG_WAKE_SOURCE_RTC 0x03
#define ELOG_WAKE_SOURCE_GPIO 0x04 #define ELOG_WAKE_SOURCE_GPIO 0x04
#define ELOG_WAKE_SOURCE_SMBUS 0x05 #define ELOG_WAKE_SOURCE_SMBUS 0x05
#define ELOG_WAKE_SOURCE_PWRBTN 0x06
struct elog_event_data_wake { struct elog_event_data_wake {
u8 source; u8 source;
u32 instance; u32 instance;

View File

@ -28,20 +28,101 @@
#include <elog.h> #include <elog.h>
#include "pch.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) void pch_log_state(void)
{ {
u16 pm1_sts, gen_pmcon_3, tco2_sts; u16 pm1_sts, gen_pmcon_3, tco2_sts;
u32 gpe0_sts, gpe0_en;
u8 gen_pmcon_2; u8 gen_pmcon_2;
int i;
struct device *lpc = dev_find_slot(0, PCI_DEVFN(0x1f, 0)); struct device *lpc = dev_find_slot(0, PCI_DEVFN(0x1f, 0));
if (!lpc) if (!lpc)
return; return;
pm1_sts = inw(DEFAULT_PMBASE + PM1_STS); pm1_sts = inw(get_pmbase() + PM1_STS);
gpe0_sts = inl(DEFAULT_PMBASE + GPE0_STS); tco2_sts = inw(get_pmbase() + TCO2_STS);
gpe0_en = inl(DEFAULT_PMBASE + GPE0_EN);
tco2_sts = inw(DEFAULT_PMBASE + TCO2_STS);
gen_pmcon_2 = pci_read_config8(lpc, GEN_PMCON_2); gen_pmcon_2 = pci_read_config8(lpc, GEN_PMCON_2);
gen_pmcon_3 = pci_read_config16(lpc, GEN_PMCON_3); gen_pmcon_3 = pci_read_config16(lpc, GEN_PMCON_3);
@ -86,6 +167,10 @@ void pch_log_state(void)
* Wake sources * Wake sources
*/ */
/* Power Button */
if (pm1_sts & (1 << 8))
elog_add_event_wake(ELOG_WAKE_SOURCE_PWRBTN, 0);
/* RTC */ /* RTC */
if (pm1_sts & (1 << 10)) if (pm1_sts & (1 << 10))
elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0); elog_add_event_wake(ELOG_WAKE_SOURCE_RTC, 0);
@ -94,21 +179,9 @@ void pch_log_state(void)
if (pm1_sts & (1 << 14)) if (pm1_sts & (1 << 14))
elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0); elog_add_event_wake(ELOG_WAKE_SOURCE_PCIE, 0);
/* PME (TODO: determine wake device) */ /* GPE */
if (gpe0_sts & (1 << 13)) if (pch_is_lp())
elog_add_event_wake(ELOG_WAKE_SOURCE_PME, 0); pch_lp_log_gpe();
else
/* Internal PME (TODO: determine wake device) */ pch_log_gpe();
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);
} }