soc/amd/stoneyridge: Add ELOG to SMM

1. Add ELOG entries to smihandler.c
2. Add save_state utilities that are needed by southbridge_smi_gsmi

BUG=b:65485690

Change-Id: I458babe1694f042215dd0e1c3277856e340de86f
Signed-off-by: John E. Kabat Jr <john.kabat@scarletltd.com>
Reviewed-on: https://review.coreboot.org/21728
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Aaron Durbin <adurbin@chromium.org>
This commit is contained in:
John E. Kabat Jr 2017-10-16 20:23:00 -06:00 committed by Martin Roth
parent 0e022038fc
commit 7057a27a44
1 changed files with 68 additions and 0 deletions

View File

@ -24,6 +24,66 @@
#include <device/pci_def.h> #include <device/pci_def.h>
#include <soc/smi.h> #include <soc/smi.h>
#include <soc/southbridge.h> #include <soc/southbridge.h>
#include <elog.h>
/* bits in smm_io_trap */
#define SMM_IO_TRAP_PORT_OFFSET 16
#define SMM_IO_TRAP_PORT_ADDRESS_MASK 0xffff
#define SMM_IO_TRAP_RW (1 << 0)
#define SMM_IO_TRAP_VALID (1 << 1)
static inline u16 get_io_address(u32 info)
{
return ((info >> SMM_IO_TRAP_PORT_OFFSET) &
SMM_IO_TRAP_PORT_ADDRESS_MASK);
}
static void *find_save_state(int cmd)
{
int core;
amd64_smm_state_save_area_t *state;
u32 smm_io_trap;
u8 reg_al;
/* Check all nodes looking for the one that issued the IO */
for (core = 0; core < CONFIG_MAX_CPUS; core++) {
state = smm_get_save_state(core);
smm_io_trap = state->smm_io_trap_offset;
/* Check for Valid IO Trap Word (bit1==1) */
if (!(smm_io_trap & SMM_IO_TRAP_VALID))
continue;
/* Make sure it was a write (bit0==0) */
if (smm_io_trap & SMM_IO_TRAP_RW)
continue;
/* Check for APMC IO port */
if (pm_acpi_smi_cmd_port() != get_io_address(smm_io_trap))
continue;
/* Check AL against the requested command */
reg_al = state->rax;
if (reg_al == cmd)
return state;
}
return NULL;
}
static void southbridge_smi_gsmi(void)
{
u8 sub_command;
amd64_smm_state_save_area_t *io_smi;
u32 reg_ebx;
io_smi = find_save_state(ELOG_GSMI_APM_CNT);
if (!io_smi)
return;
/* Command and return value in EAX */
sub_command = (io_smi->rax >> 8) & 0xff;
/* Parameter buffer in EBX */
reg_ebx = io_smi->rbx;
/* drivers/elog/gsmi.c */
io_smi->rax = gsmi_exec(sub_command, &reg_ebx);
}
static void sb_apmc_smi_handler(void) static void sb_apmc_smi_handler(void)
{ {
@ -41,6 +101,10 @@ static void sb_apmc_smi_handler(void)
reg32 &= ~(1 << 0); /* clear SCI_EN */ reg32 &= ~(1 << 0); /* clear SCI_EN */
outl(ACPI_PM1_CNT_BLK, reg32); outl(ACPI_PM1_CNT_BLK, reg32);
break; break;
case ELOG_GSMI_APM_CNT:
if (IS_ENABLED(CONFIG_ELOG_GSMI))
southbridge_smi_gsmi();
break;
} }
mainboard_smi_apmc(cmd); mainboard_smi_apmc(cmd);
@ -88,6 +152,10 @@ static void sb_slp_typ_handler(void)
} }
if (slp_typ >= ACPI_S3) { if (slp_typ >= ACPI_S3) {
/* Sleep Type Elog S3, S4, and S5 entry */
if (IS_ENABLED(CONFIG_ELOG_GSMI))
elog_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);
wbinvd(); wbinvd();
disable_all_smi_status(); disable_all_smi_status();