soc/amd/stoneyridge/southbridge.c: Fix saving _SWS parameters

PM1 and GPE0 are being stored directly to NVS, when actually what should
be saved is the index of the bit responsible for waking. Fix the procedures
and add definitions to the actual IO addresses to be read when recording
status and enable registers.

BUG=b:75996437
TEST=Build and boot grunt. Once in OS, execute a sleep and a wake. See the
message indicating which indexes are being save in NVS for _SWS. Try sleep
stress test, verify that the index is different from that of power button.

Change-Id: I8bafc7bb7dd66e7f0eb8499e748535bbdcac5f53
Signed-off-by: Richard Spiegel <richard.spiegel@silverbackltd.com>
Reviewed-on: https://review.coreboot.org/26547
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martinroth@google.com>
This commit is contained in:
Richard Spiegel 2018-05-25 15:49:33 -07:00 committed by Martin Roth
parent 9b05af367f
commit 572f4988dd
3 changed files with 52 additions and 14 deletions

View File

@ -52,9 +52,13 @@
#define ACPI_SMI_CTL_PORT 0xb2 #define ACPI_SMI_CTL_PORT 0xb2
#define STONEYRIDGE_ACPI_IO_BASE CONFIG_STONEYRIDGE_ACPI_IO_BASE #define STONEYRIDGE_ACPI_IO_BASE CONFIG_STONEYRIDGE_ACPI_IO_BASE
#define ACPI_PM_EVT_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x00) /* 4 bytes */ #define ACPI_PM_EVT_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x00) /* 4 bytes */
#define ACPI_PM1_STS (ACPI_PM_EVT_BLK + 0x00) /* 2 bytes */
#define ACPI_PM1_EN (ACPI_PM_EVT_BLK + 0x02) /* 2 bytes */
#define ACPI_PM1_CNT_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x04) /* 2 bytes */ #define ACPI_PM1_CNT_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x04) /* 2 bytes */
#define ACPI_CPU_CONTROL (STONEYRIDGE_ACPI_IO_BASE + 0x08) /* 6 bytes */ #define ACPI_CPU_CONTROL (STONEYRIDGE_ACPI_IO_BASE + 0x08) /* 6 bytes */
#define ACPI_GPE0_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x10) /* 8 bytes */ #define ACPI_GPE0_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x10) /* 8 bytes */
#define ACPI_GPE0_STS (ACPI_GPE0_BLK + 0x00) /* 4 bytes */
#define ACPI_GPE0_EN (ACPI_GPE0_BLK + 0x04) /* 4 bytes */
#define ACPI_PM_TMR_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x18) /* 4 bytes */ #define ACPI_PM_TMR_BLK (STONEYRIDGE_ACPI_IO_BASE + 0x18) /* 4 bytes */
#define SMB_BASE_ADDR 0xb00 #define SMB_BASE_ADDR 0xb00
#define PM2_INDEX 0xcd0 #define PM2_INDEX 0xcd0

View File

@ -353,6 +353,9 @@
#define FCH_AOAC_STAT0 BIT(6) #define FCH_AOAC_STAT0 BIT(6)
#define FCH_AOAC_STAT1 BIT(7) #define FCH_AOAC_STAT1 BIT(7)
#define PM1_LIMIT 16
#define GPE0_LIMIT 28
struct stoneyridge_aoac { struct stoneyridge_aoac {
int enable; int enable;
int status; int status;

View File

@ -616,8 +616,8 @@ static void print_num_status_bits(int num_bits, uint32_t status,
static uint16_t reset_pm1_status(void) static uint16_t reset_pm1_status(void)
{ {
uint16_t pm1_sts = inw(ACPI_PM_EVT_BLK); uint16_t pm1_sts = inw(ACPI_PM1_STS);
outw(pm1_sts, ACPI_PM_EVT_BLK); outw(pm1_sts, ACPI_PM1_STS);
return pm1_sts; return pm1_sts;
} }
@ -663,21 +663,24 @@ static void sb_log_pm1_status(uint16_t pm1_sts)
} }
struct soc_amd_sws { struct soc_amd_sws {
uint32_t pm1i; uint16_t pm1_sts;
uint32_t gevent; uint16_t pm1_en;
uint32_t gpe0_sts;
uint32_t gpe0_en;
}; };
static struct soc_amd_sws sws; static struct soc_amd_sws sws;
static void sb_save_sws(uint32_t pm1_status) static void sb_save_sws(uint16_t pm1_status)
{ {
uint32_t reg32; uint32_t reg32;
sws.pm1i = pm1_status; sws.pm1_sts = pm1_status;
reg32 = inl(ACPI_GPE0_BLK); sws.pm1_en = inw(ACPI_PM1_EN);
outl(ACPI_GPE0_BLK, reg32); reg32 = inl(ACPI_GPE0_STS);
reg32 &= inl(ACPI_GPE0_BLK + sizeof(uint32_t)); outl(ACPI_GPE0_STS, reg32);
sws.gevent = reg32; sws.gpe0_sts = reg32;
sws.gpe0_en = inl(ACPI_GPE0_EN);
} }
static void sb_clear_pm1_status(void) static void sb_clear_pm1_status(void)
@ -689,19 +692,47 @@ static void sb_clear_pm1_status(void)
print_pm1_status(pm1_sts); print_pm1_status(pm1_sts);
} }
static int get_index_bit(uint32_t value, uint16_t limit)
{
uint16_t i;
uint32_t t;
if (limit >= sizeof(uint32_t))
return -1;
/* get a mask of valid bits. Ex limit = 3, set bits 0-2 */
t = (1 << limit) - 1;
if ((value & t) == 0)
return -1;
t = 1;
for (i = 0; i < limit; i++) {
if (value & t)
break;
t <<= 1;
}
return i;
}
static void set_nvs_sws(void *unused) static void set_nvs_sws(void *unused)
{ {
struct global_nvs_t *gnvs; struct global_nvs_t *gnvs;
int index;
gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS); gnvs = cbmem_find(CBMEM_ID_ACPI_GNVS);
if (gnvs == NULL) if (gnvs == NULL)
return; return;
gnvs->pm1i = sws.pm1i; index = get_index_bit(sws.pm1_sts & sws.pm1_en, PM1_LIMIT);
gnvs->gpei = sws.gevent; if (index < 0)
gnvs->pm1i = ~0ULL;
else
gnvs->pm1i = index;
printk(BIOS_DEBUG, "Loaded _SWS parameters PM1 0x%08x, EVENT 0x%08x into nvs\n", index = get_index_bit(sws.gpe0_sts & sws.gpe0_en, GPE0_LIMIT);
sws.pm1i, sws.gevent); if (index < 0)
gnvs->gpei = ~0ULL;
else
gnvs->gpei = index;
} }
BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL); BOOT_STATE_INIT_ENTRY(BS_OS_RESUME, BS_ON_ENTRY, set_nvs_sws, NULL);