blob: f9c4a5450a4211e7943067910934f4a2095366cd [file] [log] [blame]
Felix Held4a8cd722020-04-18 22:26:39 +02001/* SPDX-License-Identifier: GPL-2.0-or-later */
Marc Jones24484842017-05-04 21:17:45 -06002
Furquan Shaikh76cedd22020-05-02 10:24:23 -07003#include <acpi/acpi.h>
Marshall Dawson4ee83b22019-05-03 11:44:22 -06004#include <amdblocks/acpi.h>
Felix Helde4a7e462021-03-09 16:42:17 +01005#include <amdblocks/acpimmio.h>
Felix Helda5a52952020-12-01 18:14:01 +01006#include <amdblocks/smi.h>
Felix Helda3a66b62021-02-10 03:29:48 +01007#include <amdblocks/smm.h>
Felix Helde4a7e462021-03-09 16:42:17 +01008#include <arch/hlt.h>
9#include <arch/io.h>
10#include <console/console.h>
11#include <cpu/x86/cache.h>
12#include <cpu/x86/smm.h>
John E. Kabat Jr7057a272017-10-16 20:23:00 -060013#include <elog.h>
Felix Helde4a7e462021-03-09 16:42:17 +010014#include <soc/smi.h>
15#include <soc/southbridge.h>
Felix Held2e978972021-02-10 16:48:23 +010016#include <types.h>
John E. Kabat Jr7057a272017-10-16 20:23:00 -060017
Felix Helda2db88e2021-02-10 16:46:11 +010018static void fch_apmc_smi_handler(void)
Marc Jones24484842017-05-04 21:17:45 -060019{
Marshall Dawson66e62da2017-09-27 13:32:38 -060020 const uint8_t cmd = inb(pm_acpi_smi_cmd_port());
Marc Jones24484842017-05-04 21:17:45 -060021
22 switch (cmd) {
Marshall Dawsone9b862e2017-09-22 15:14:46 -060023 case APM_CNT_ACPI_ENABLE:
Marshall Dawson4ee83b22019-05-03 11:44:22 -060024 acpi_enable_sci();
Marc Jones24484842017-05-04 21:17:45 -060025 break;
Marshall Dawsone9b862e2017-09-22 15:14:46 -060026 case APM_CNT_ACPI_DISABLE:
Marshall Dawson4ee83b22019-05-03 11:44:22 -060027 acpi_disable_sci();
Marc Jones24484842017-05-04 21:17:45 -060028 break;
Patrick Georgid61839c2018-12-03 16:10:33 +010029 case APM_CNT_ELOG_GSMI:
Julius Wernercd49cce2019-03-05 16:53:33 -080030 if (CONFIG(ELOG_GSMI))
Felix Held90bcdb42021-03-08 23:54:18 +010031 handle_smi_gsmi();
John E. Kabat Jr7057a272017-10-16 20:23:00 -060032 break;
Matt DeVillier9cc16032020-01-19 00:17:29 -060033 case APM_CNT_SMMSTORE:
34 if (CONFIG(SMMSTORE))
Felix Held90bcdb42021-03-08 23:54:18 +010035 handle_smi_store();
Matt DeVillier9cc16032020-01-19 00:17:29 -060036 break;
Marc Jones24484842017-05-04 21:17:45 -060037 }
38
39 mainboard_smi_apmc(cmd);
40}
41
Felix Helda2db88e2021-02-10 16:46:11 +010042static void fch_slp_typ_handler(void)
Marshall Dawson081851a2017-10-02 14:03:57 -060043{
Marshall Dawsone1b1ec72018-10-07 21:45:47 -060044 uint32_t pci_ctrl, reg32;
45 uint16_t pm1cnt, reg16;
Marshall Dawson081851a2017-10-02 14:03:57 -060046 uint8_t slp_typ, rst_ctrl;
47
48 /* Figure out SLP_TYP */
Richard Spiegele24d7952018-10-26 13:25:01 -070049 pm1cnt = acpi_read16(MMIO_ACPI_PM1_CNT_BLK);
Marshall Dawsone1b1ec72018-10-07 21:45:47 -060050 printk(BIOS_SPEW, "SMI#: SLP = 0x%04x\n", pm1cnt);
Marshall Dawson081851a2017-10-02 14:03:57 -060051 slp_typ = acpi_sleep_from_pm1(pm1cnt);
52
53 /* Do any mainboard sleep handling */
54 mainboard_smi_sleep(slp_typ);
55
56 switch (slp_typ) {
57 case ACPI_S0:
58 printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
59 break;
60 case ACPI_S3:
61 printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
62 break;
63 case ACPI_S4:
64 printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
65 break;
66 case ACPI_S5:
67 printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
68 break;
69 default:
70 printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
71 break;
72 }
73
74 if (slp_typ >= ACPI_S3) {
John E. Kabat Jr7057a272017-10-16 20:23:00 -060075 /* Sleep Type Elog S3, S4, and S5 entry */
Kyösti Mälkki9dd1a122019-11-06 11:04:27 +020076 elog_gsmi_add_event_byte(ELOG_TYPE_ACPI_ENTER, slp_typ);
John E. Kabat Jr7057a272017-10-16 20:23:00 -060077
Marshall Dawson081851a2017-10-02 14:03:57 -060078 wbinvd();
79
Felix Held4f69ab72021-02-10 01:26:07 +010080 clear_all_smi_status();
Marshall Dawson081851a2017-10-02 14:03:57 -060081
82 /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */
83 pci_ctrl = pm_read32(PM_PCI_CTRL);
84 pci_ctrl &= ~FORCE_SLPSTATE_RETRY;
85 pci_ctrl |= FORCE_STPCLK_RETRY;
86 pm_write32(PM_PCI_CTRL, pci_ctrl);
87
88 /* Enable SlpTyp */
89 rst_ctrl = pm_read8(PM_RST_CTRL1);
90 rst_ctrl |= SLPTYPE_CONTROL_EN;
91 pm_write8(PM_RST_CTRL1, rst_ctrl);
92
Richard Spiegelb74e3992018-08-20 13:52:44 -070093 /*
94 * Before the final command, check if there's pending wake
95 * event. Read enable first, so that reading the actual status
96 * is as close as possible to entering S3. The idea is to
97 * minimize the opportunity for a wake event to happen before
98 * actually entering S3. If there's a pending wake event, log
99 * it and continue normal path. S3 will fail and the wake event
100 * becomes a SCI.
101 */
Julius Wernercd49cce2019-03-05 16:53:33 -0800102 if (CONFIG(ELOG_GSMI)) {
Richard Spiegele24d7952018-10-26 13:25:01 -0700103 reg16 = acpi_read16(MMIO_ACPI_PM1_EN);
104 reg16 &= acpi_read16(MMIO_ACPI_PM1_STS);
Richard Spiegelb74e3992018-08-20 13:52:44 -0700105 if (reg16)
106 elog_add_extended_event(
107 ELOG_SLEEP_PENDING_PM1_WAKE,
108 (u32)reg16);
109
Richard Spiegele24d7952018-10-26 13:25:01 -0700110 reg32 = acpi_read32(MMIO_ACPI_GPE0_EN);
111 reg32 &= acpi_read32(MMIO_ACPI_GPE0_STS);
Richard Spiegelb74e3992018-08-20 13:52:44 -0700112 if (reg32)
113 elog_add_extended_event(
114 ELOG_SLEEP_PENDING_GPE0_WAKE,
115 reg32);
Julius Wernercd49cce2019-03-05 16:53:33 -0800116 } /* if (CONFIG(ELOG_GSMI)) */
Richard Spiegelb74e3992018-08-20 13:52:44 -0700117
Richard Spiegele24d7952018-10-26 13:25:01 -0700118 /*
119 * An IO cycle is required to trigger the STPCLK/STPGNT
120 * handshake when the Pm1 write is reissued.
121 */
Marshall Dawson19cae7c2019-05-03 13:06:55 -0600122 outw(pm1cnt | SLP_EN, pm_read16(PM1_CNT_BLK));
Marshall Dawson081851a2017-10-02 14:03:57 -0600123 hlt();
124 }
125}
126
Marc Jones24484842017-05-04 21:17:45 -0600127int southbridge_io_trap_handler(int smif)
128{
129 return 0;
130}
131
Marshall Dawson36a23562017-09-28 17:21:09 -0600132/*
133 * Table of functions supported in the SMI handler. Note that SMI source setup
134 * in southbridge.c is unrelated to this list.
135 */
Daniel Kurtz963419a2018-04-17 17:45:01 -0600136static const struct smi_sources_t smi_sources[] = {
Felix Helda2db88e2021-02-10 16:46:11 +0100137 { .type = SMITYPE_SMI_CMD_PORT, .handler = fch_apmc_smi_handler },
138 { .type = SMITYPE_SLP_TYP, .handler = fch_slp_typ_handler},
Marshall Dawson36a23562017-09-28 17:21:09 -0600139};
140
Felix Helda3a66b62021-02-10 03:29:48 +0100141void *get_smi_source_handler(int source)
Marc Jones24484842017-05-04 21:17:45 -0600142{
Felix Held2e978972021-02-10 16:48:23 +0100143 size_t i;
Marc Jones24484842017-05-04 21:17:45 -0600144
Marshall Dawson36a23562017-09-28 17:21:09 -0600145 for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++)
146 if (smi_sources[i].type == source)
147 return smi_sources[i].handler;
148
149 return NULL;
150}