summaryrefslogtreecommitdiff
path: root/src/soc/amd/mendocino/smihandler.c
diff options
context:
space:
mode:
authorJon Murphy <jpmurphy@google.com>2022-08-05 15:43:44 -0600
committerMartin Roth <martin.roth@amd.corp-partner.google.com>2022-08-11 19:15:30 +0000
commit4f732420526fdc1c969e910daca573dca72d7b82 (patch)
tree26c74fa55c89edbdd7c36be5b966401910437694 /src/soc/amd/mendocino/smihandler.c
parent251e26683e25fdbef329e9e731319ef95b0f7327 (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.c154
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;
+}