1 /* SPDX-License-Identifier: GPL-2.0-or-later */
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>
11 #include <console/console.h>
12 #include <cpu/x86/cache.h>
13 #include <cpu/x86/smm.h>
16 #include <soc/southbridge.h>
20 * Both the psp_notify_sx_info and the smu_sx_entry call will clobber the SMN index register
21 * during the SMN accesses. Since the SMI handler is the last thing that gets called before
22 * entering S3, this won't interfere with any indirect SMN accesses via the same register pair.
24 static void fch_slp_typ_handler(void)
28 uint8_t slp_typ
, rst_ctrl
;
30 /* Figure out SLP_TYP */
31 pm1cnt
= acpi_read16(MMIO_ACPI_PM1_CNT_BLK
);
32 printk(BIOS_SPEW
, "SMI#: SLP = 0x%04x\n", pm1cnt
);
33 slp_typ
= acpi_sleep_from_pm1(pm1cnt
);
35 /* Do any mainboard sleep handling */
36 mainboard_smi_sleep(slp_typ
);
40 printk(BIOS_DEBUG
, "SMI#: Entering S0 (On)\n");
43 printk(BIOS_DEBUG
, "SMI#: Entering S3 (Suspend-To-RAM)\n");
46 printk(BIOS_DEBUG
, "SMI#: Entering S4 (Suspend-To-Disk)\n");
49 printk(BIOS_DEBUG
, "SMI#: Entering S5 (Soft Power off)\n");
52 printk(BIOS_DEBUG
, "SMI#: ERROR: SLP_TYP reserved\n");
56 if (slp_typ
>= ACPI_S3
) {
59 clear_all_smi_status();
61 /* Do not send SMI before AcpiPm1CntBlkx00[SlpTyp] */
62 pci_ctrl
= pm_read32(PM_PCI_CTRL
);
63 pci_ctrl
&= ~FORCE_SLPSTATE_RETRY
;
64 pm_write32(PM_PCI_CTRL
, pci_ctrl
);
67 rst_ctrl
= pm_read8(PM_RST_CTRL1
);
68 rst_ctrl
|= SLPTYPE_CONTROL_EN
;
69 pm_write8(PM_RST_CTRL1
, rst_ctrl
);
71 smu_sx_entry(); /* Leave SlpTypeEn clear, SMU will set */
72 printk(BIOS_ERR
, "System did not go to sleep\n");
78 * Table of functions supported in the SMI handler. Note that SMI source setup
79 * in fch.c is unrelated to this list.
81 static const struct smi_sources_t smi_sources
[] = {
82 { .type
= SMITYPE_SMI_CMD_PORT
, .handler
= fch_apmc_smi_handler
},
83 { .type
= SMITYPE_SLP_TYP
, .handler
= fch_slp_typ_handler
},
84 { .type
= SMITYPE_PSP
, .handler
= psp_smi_handler
},
87 void *get_smi_source_handler(int source
)
91 for (i
= 0 ; i
< ARRAY_SIZE(smi_sources
) ; i
++)
92 if (smi_sources
[i
].type
== source
)
93 return smi_sources
[i
].handler
;