diff options
author | Jon Murphy <jpmurphy@google.com> | 2022-08-05 15:43:44 -0600 |
---|---|---|
committer | Martin Roth <martin.roth@amd.corp-partner.google.com> | 2022-08-11 19:15:30 +0000 |
commit | 4f732420526fdc1c969e910daca573dca72d7b82 (patch) | |
tree | 26c74fa55c89edbdd7c36be5b966401910437694 /src/soc/amd/mendocino/smihandler.c | |
parent | 251e26683e25fdbef329e9e731319ef95b0f7327 (diff) |
treewide: Rename Sabrina to Mendocino
'Mendocino' was an embargoed name and could previously not be used
in references to Skyrim. coreboot has references to sabrina both
in directory structure and in files. This will make life difficult
for people looking for Mendocino support in the long term. The code
name should be replaced with "mendocino".
BUG=b:239072117
TEST=Builds
Cq-Depend: chromium:3764023
Cq-Depend: chromium:3763392
Cq-Depend: chrome-internal:4876777
Signed-off-by: Jon Murphy <jpmurphy@google.com>
Change-Id: I2d0f76fde07a209a79f7e1596cc8064e53f06ada
Reviewed-on: https://review.coreboot.org/c/coreboot/+/65861
Tested-by: build bot (Jenkins) <no-reply@coreboot.org>
Reviewed-by: Martin Roth <martin.roth@amd.corp-partner.google.com>
Diffstat (limited to 'src/soc/amd/mendocino/smihandler.c')
-rw-r--r-- | src/soc/amd/mendocino/smihandler.c | 154 |
1 files changed, 154 insertions, 0 deletions
diff --git a/src/soc/amd/mendocino/smihandler.c b/src/soc/amd/mendocino/smihandler.c new file mode 100644 index 0000000000..9fda2f9c1a --- /dev/null +++ b/src/soc/amd/mendocino/smihandler.c @@ -0,0 +1,154 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +/* TODO: Check if this is still correct */ + +#include <acpi/acpi.h> +#include <amdblocks/acpi.h> +#include <amdblocks/acpimmio.h> +#include <amdblocks/psp.h> +#include <amdblocks/smi.h> +#include <amdblocks/smm.h> +#include <arch/hlt.h> +#include <arch/io.h> +#include <console/console.h> +#include <cpu/x86/cache.h> +#include <cpu/x86/smm.h> +#include <elog.h> +#include <soc/smi.h> +#include <soc/smu.h> +#include <soc/southbridge.h> +#include <types.h> + +static void fch_apmc_smi_handler(void) +{ + const uint8_t cmd = inb(pm_acpi_smi_cmd_port()); + + switch (cmd) { + case APM_CNT_ACPI_ENABLE: + acpi_clear_pm_gpe_status(); + acpi_enable_sci(); + break; + case APM_CNT_ACPI_DISABLE: + acpi_disable_sci(); + break; + case APM_CNT_ELOG_GSMI: + if (CONFIG(ELOG_GSMI)) + handle_smi_gsmi(); + break; + case APM_CNT_SMMSTORE: + if (CONFIG(SMMSTORE)) + handle_smi_store(); + break; + case APM_CNT_SMMINFO: + psp_notify_smm(); + break; + } + + mainboard_smi_apmc(cmd); +} + +static void fch_slp_typ_handler(void) +{ + uint32_t pci_ctrl, reg32; + uint16_t pm1cnt, reg16; + uint8_t slp_typ, rst_ctrl; + + /* Figure out SLP_TYP */ + pm1cnt = acpi_read16(MMIO_ACPI_PM1_CNT_BLK); + printk(BIOS_SPEW, "SMI#: SLP = 0x%04x\n", pm1cnt); + slp_typ = acpi_sleep_from_pm1(pm1cnt); + + /* Do any mainboard sleep handling */ + mainboard_smi_sleep(slp_typ); + + switch (slp_typ) { + case ACPI_S0: + printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n"); + break; + case ACPI_S3: + printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n"); + break; + case ACPI_S4: + printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n"); + break; + case ACPI_S5: + printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n"); + break; + default: + printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n"); + break; + } + + if (slp_typ >= ACPI_S3) { + wbinvd(); + + clear_all_smi_status(); + + /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */ + pci_ctrl = pm_read32(PM_PCI_CTRL); + pci_ctrl &= ~FORCE_SLPSTATE_RETRY; + pm_write32(PM_PCI_CTRL, pci_ctrl); + + /* Enable SlpTyp */ + rst_ctrl = pm_read8(PM_RST_CTRL1); + rst_ctrl |= SLPTYPE_CONTROL_EN; + pm_write8(PM_RST_CTRL1, rst_ctrl); + + /* + * Before the final command, check if there's pending wake + * event. Read enable first, so that reading the actual status + * is as close as possible to entering S3. The idea is to + * minimize the opportunity for a wake event to happen before + * actually entering S3. If there's a pending wake event, log + * it and continue normal path. S3 will fail and the wake event + * becomes a SCI. + */ + if (CONFIG(ELOG_GSMI)) { + reg16 = acpi_read16(MMIO_ACPI_PM1_EN); + reg16 &= acpi_read16(MMIO_ACPI_PM1_STS); + if (reg16) + elog_add_extended_event( + ELOG_SLEEP_PENDING_PM1_WAKE, + (u32)reg16); + + reg32 = acpi_read32(MMIO_ACPI_GPE0_EN); + reg32 &= acpi_read32(MMIO_ACPI_GPE0_STS); + if (reg32) + elog_add_extended_event( + ELOG_SLEEP_PENDING_GPE0_WAKE, + reg32); + } /* if (CONFIG(ELOG_GSMI)) */ + + if (slp_typ == ACPI_S3) + psp_notify_sx_info(ACPI_S3); + + smu_sx_entry(); /* Leave SlpTypeEn clear, SMU will set */ + printk(BIOS_ERR, "Error: System did not go to sleep\n"); + hlt(); + } +} + +int southbridge_io_trap_handler(int smif) +{ + return 0; +} + +/* + * Table of functions supported in the SMI handler. Note that SMI source setup + * in fch.c is unrelated to this list. + */ +static const struct smi_sources_t smi_sources[] = { + { .type = SMITYPE_SMI_CMD_PORT, .handler = fch_apmc_smi_handler }, + { .type = SMITYPE_SLP_TYP, .handler = fch_slp_typ_handler}, +}; + +void *get_smi_source_handler(int source) +{ + size_t i; + + for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++) + if (smi_sources[i].type == source) + return smi_sources[i].handler; + + return NULL; +} |