coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
smihandler.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 
3 #include <acpi/acpi.h>
4 #include <amdblocks/acpi.h>
5 #include <amdblocks/acpimmio.h>
6 #include <amdblocks/psp.h>
7 #include <amdblocks/smi.h>
8 #include <amdblocks/smm.h>
9 #include <arch/hlt.h>
10 #include <arch/io.h>
11 #include <console/console.h>
12 #include <console/cbmem_console.h>
13 #include <cpu/x86/cache.h>
14 #include <cpu/x86/smm.h>
15 #include <elog.h>
16 #include <soc/psp_transfer.h>
17 #include <soc/smi.h>
18 #include <soc/smu.h>
19 #include <soc/southbridge.h>
20 #include <types.h>
21 
22 static void fch_apmc_smi_handler(void)
23 {
24  const uint8_t cmd = inb(pm_acpi_smi_cmd_port());
25 
26  switch (cmd) {
30  break;
33  break;
34  case APM_CNT_ELOG_GSMI:
35  if (CONFIG(ELOG_GSMI))
37  break;
38  case APM_CNT_SMMSTORE:
39  if (CONFIG(SMMSTORE))
41  break;
42  case APM_CNT_SMMINFO:
44  break;
45  }
46 
47  mainboard_smi_apmc(cmd);
48 }
49 
50 static void fch_slp_typ_handler(void)
51 {
52  uint32_t pci_ctrl, reg32;
53  uint16_t pm1cnt, reg16;
54  uint8_t slp_typ, rst_ctrl;
55 
56  /* Figure out SLP_TYP */
58  printk(BIOS_SPEW, "SMI#: SLP = 0x%04x\n", pm1cnt);
59  slp_typ = acpi_sleep_from_pm1(pm1cnt);
60 
61  /* Do any mainboard sleep handling */
62  mainboard_smi_sleep(slp_typ);
63 
64  switch (slp_typ) {
65  case ACPI_S0:
66  printk(BIOS_DEBUG, "SMI#: Entering S0 (On)\n");
67  break;
68  case ACPI_S3:
69  printk(BIOS_DEBUG, "SMI#: Entering S3 (Suspend-To-RAM)\n");
70  break;
71  case ACPI_S4:
72  printk(BIOS_DEBUG, "SMI#: Entering S4 (Suspend-To-Disk)\n");
73  break;
74  case ACPI_S5:
75  printk(BIOS_DEBUG, "SMI#: Entering S5 (Soft Power off)\n");
76  break;
77  default:
78  printk(BIOS_DEBUG, "SMI#: ERROR: SLP_TYP reserved\n");
79  break;
80  }
81 
82  if (slp_typ >= ACPI_S3) {
83  wbinvd();
84 
86 
87  /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */
88  pci_ctrl = pm_read32(PM_PCI_CTRL);
89  pci_ctrl &= ~FORCE_SLPSTATE_RETRY;
90  pm_write32(PM_PCI_CTRL, pci_ctrl);
91 
92  /* Enable SlpTyp */
93  rst_ctrl = pm_read8(PM_RST_CTRL1);
94  rst_ctrl |= SLPTYPE_CONTROL_EN;
95  pm_write8(PM_RST_CTRL1, rst_ctrl);
96 
97  /*
98  * Before the final command, check if there's pending wake
99  * event. Read enable first, so that reading the actual status
100  * is as close as possible to entering S3. The idea is to
101  * minimize the opportunity for a wake event to happen before
102  * actually entering S3. If there's a pending wake event, log
103  * it and continue normal path. S3 will fail and the wake event
104  * becomes a SCI.
105  */
106  if (CONFIG(ELOG_GSMI)) {
107  reg16 = acpi_read16(MMIO_ACPI_PM1_EN);
108  reg16 &= acpi_read16(MMIO_ACPI_PM1_STS);
109  if (reg16)
112  (u32)reg16);
113 
116  if (reg32)
119  reg32);
120  } /* if (CONFIG(ELOG_GSMI)) */
121 
122  if (slp_typ == ACPI_S3)
124 
125  smu_sx_entry(); /* Leave SlpTypeEn clear, SMU will set */
126  printk(BIOS_ERR, "System did not go to sleep\n");
127  hlt();
128  }
129 }
130 
132 {
133  return 0;
134 }
135 
136 /*
137  * Table of functions supported in the SMI handler. Note that SMI source setup
138  * in fch.c is unrelated to this list.
139  */
140 static const struct smi_sources_t smi_sources[] = {
142  { .type = SMITYPE_SLP_TYP, .handler = fch_slp_typ_handler},
143 };
144 
145 void *get_smi_source_handler(int source)
146 {
147  size_t i;
148 
149  for (i = 0 ; i < ARRAY_SIZE(smi_sources) ; i++)
150  if (smi_sources[i].type == source)
151  return smi_sources[i].handler;
152 
153  return NULL;
154 }
155 
157 {
158  if (CONFIG(VBOOT_STARTS_BEFORE_BOOTBLOCK) && __CBMEM_CONSOLE_ENABLE__)
160 }
#define SLPTYPE_CONTROL_EN
Definition: acpimmio.h:32
static void pm_write32(uint8_t reg, uint32_t value)
Definition: acpimmio.h:191
static uint32_t acpi_read32(uint8_t reg)
Definition: acpimmio.h:216
static uint8_t pm_read8(uint8_t reg)
Definition: acpimmio.h:166
static uint32_t pm_read32(uint8_t reg)
Definition: acpimmio.h:176
static uint16_t acpi_read16(uint8_t reg)
Definition: acpimmio.h:211
static void pm_write8(uint8_t reg, uint8_t value)
Definition: acpimmio.h:181
#define PM_RST_CTRL1
Definition: acpimmio.h:31
static __always_inline void hlt(void)
Definition: hlt.h:6
#define ARRAY_SIZE(a)
Definition: helpers.h:12
#define __CBMEM_CONSOLE_ENABLE__
Definition: cbmem_console.h:11
void replay_transfer_buffer_cbmemc(void)
void smu_sx_entry(void)
Definition: smu.c:11
#define FORCE_SLPSTATE_RETRY
Definition: southbridge.h:12
#define PM_PCI_CTRL
Definition: southbridge.h:11
#define ELOG_SLEEP_PENDING_GPE0_WAKE
Definition: elog.h:298
#define ELOG_SLEEP_PENDING_PM1_WAKE
Definition: elog.h:297
#define printk(level,...)
Definition: stdlib.h:16
void __weak mainboard_smi_sleep(u8 slp_typ)
Definition: smihandler.c:210
int __weak mainboard_smi_apmc(u8 data)
Definition: smihandler.c:209
u8 inb(u16 port)
int elog_add_extended_event(u8 type, u32 complement)
Definition: elog.c:892
@ CONFIG
Definition: dsi_common.h:201
@ ACPI_S5
Definition: acpi.h:1385
@ ACPI_S4
Definition: acpi.h:1384
@ ACPI_S3
Definition: acpi.h:1383
@ ACPI_S0
Definition: acpi.h:1380
static void wbinvd(void)
Definition: cache.h:15
#define APM_CNT_ELOG_GSMI
Definition: smm.h:29
uint16_t pm_acpi_smi_cmd_port(void)
Definition: smi.c:6
#define APM_CNT_ACPI_DISABLE
Definition: smm.h:21
#define APM_CNT_ACPI_ENABLE
Definition: smm.h:22
#define APM_CNT_SMMSTORE
Definition: smm.h:28
#define APM_CNT_SMMINFO
Definition: smm.h:27
unsigned int type
Definition: edid.c:57
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_SPEW
BIOS_SPEW - Excessively verbose output.
Definition: loglevel.h:142
int psp_notify_smm(void)
Definition: psp_smm.c:37
void psp_notify_sx_info(u8 sleep_type)
Definition: psp_smm.c:77
void handle_smi_store(void)
void handle_smi_gsmi(void)
#define SMITYPE_SLP_TYP
Definition: smi.h:107
#define SMITYPE_SMI_CMD_PORT
Definition: smi.h:113
static void fch_apmc_smi_handler(void)
Definition: smihandler.c:22
void * get_smi_source_handler(int source)
Definition: smihandler.c:145
int southbridge_io_trap_handler(int smif)
Definition: smihandler.c:131
static const struct smi_sources_t smi_sources[]
Definition: smihandler.c:140
static void fch_slp_typ_handler(void)
Definition: smihandler.c:50
void smm_soc_early_init(void)
Definition: smihandler.c:156
void acpi_enable_sci(void)
Definition: acpi.c:126
void acpi_clear_pm_gpe_status(void)
Definition: acpi.c:90
void acpi_disable_sci(void)
Definition: acpi.c:135
#define MMIO_ACPI_PM1_EN
Definition: acpi.h:13
#define MMIO_ACPI_GPE0_EN
Definition: acpi.h:21
#define MMIO_ACPI_GPE0_STS
Definition: acpi.h:20
#define MMIO_ACPI_PM1_STS
Definition: acpi.h:12
#define MMIO_ACPI_PM1_CNT_BLK
Definition: acpi.h:14
void clear_all_smi_status(void)
Definition: smi_util.c:142
#define NULL
Definition: stddef.h:19
unsigned short uint16_t
Definition: stdint.h:11
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned char uint8_t
Definition: stdint.h:8
void(* handler)(void)
Definition: smi.h:34
int type
Definition: smi.h:33