diff options
author | John E. Kabat Jr <john.kabat@scarletltd.com> | 2017-10-16 20:23:00 -0600 |
---|---|---|
committer | Martin Roth <martinroth@google.com> | 2017-11-21 01:37:03 +0000 |
commit | 7057a27a44e43fa7f018e82121600a7291daffe2 (patch) | |
tree | a4ea63d12195e046386b493f454a48dc11a6df94 | |
parent | 0e022038fc4b02d9df304765d2c4259c4cc7e1bf (diff) |
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>
-rw-r--r-- | src/soc/amd/stoneyridge/smihandler.c | 68 |
1 files changed, 68 insertions, 0 deletions
diff --git a/src/soc/amd/stoneyridge/smihandler.c b/src/soc/amd/stoneyridge/smihandler.c index a0748fe2fc..7cc8900aa1 100644 --- a/src/soc/amd/stoneyridge/smihandler.c +++ b/src/soc/amd/stoneyridge/smihandler.c @@ -24,6 +24,66 @@ #include <device/pci_def.h> #include <soc/smi.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, ®_ebx); +} static void sb_apmc_smi_handler(void) { @@ -41,6 +101,10 @@ static void sb_apmc_smi_handler(void) reg32 &= ~(1 << 0); /* clear SCI_EN */ outl(ACPI_PM1_CNT_BLK, reg32); break; + case ELOG_GSMI_APM_CNT: + if (IS_ENABLED(CONFIG_ELOG_GSMI)) + southbridge_smi_gsmi(); + break; } mainboard_smi_apmc(cmd); @@ -88,6 +152,10 @@ static void sb_slp_typ_handler(void) } 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(); disable_all_smi_status(); |