diff options
Diffstat (limited to 'src/soc')
-rw-r--r-- | src/soc/amd/genoa/Kconfig | 6 | ||||
-rw-r--r-- | src/soc/amd/genoa/Makefile.inc | 4 | ||||
-rw-r--r-- | src/soc/amd/genoa/chipset.cb | 3 | ||||
-rw-r--r-- | src/soc/amd/genoa/cpu.c | 26 | ||||
-rw-r--r-- | src/soc/amd/genoa/include/soc/cpu.h | 9 | ||||
-rw-r--r-- | src/soc/amd/genoa/smihandler.c | 96 |
6 files changed, 142 insertions, 2 deletions
diff --git a/src/soc/amd/genoa/Kconfig b/src/soc/amd/genoa/Kconfig index 2e30df749c..397a81f620 100644 --- a/src/soc/amd/genoa/Kconfig +++ b/src/soc/amd/genoa/Kconfig @@ -7,8 +7,10 @@ config SOC_SPECIFIC_OPTIONS def_bool y select ARCH_X86 select HAVE_EXP_X86_64_SUPPORT + select HAVE_SMI_HANDLER select RESET_VECTOR_IN_RAM select SOC_AMD_COMMON + select SOC_AMD_COMMON_BLOCK_ACPI select SOC_AMD_COMMON_BLOCK_ACPIMMIO select SOC_AMD_COMMON_BLOCK_AOAC select SOC_AMD_COMMON_BLOCK_BANKED_GPIOS @@ -25,6 +27,7 @@ config SOC_SPECIFIC_OPTIONS select SOC_AMD_COMMON_BLOCK_PSP_GEN2 select SOC_AMD_COMMON_BLOCK_PSP_SPL select SOC_AMD_COMMON_BLOCK_SMI + select SOC_AMD_COMMON_BLOCK_SMM select SOC_AMD_COMMON_BLOCK_SMU select SOC_AMD_COMMON_BLOCK_SMU_SX_ENTRY select SOC_AMD_COMMON_BLOCK_TSC @@ -151,6 +154,9 @@ config PSP_SOFTFUSE_BITS See #57299 (NDA) for additional bit definitions. endmenu +config SMM_TSEG_SIZE + hex + default 0x800000 #TODO: Check if the value of HEAP_SIZE is optimal config HEAP_SIZE diff --git a/src/soc/amd/genoa/Makefile.inc b/src/soc/amd/genoa/Makefile.inc index 506f6cf279..96acc43b31 100644 --- a/src/soc/amd/genoa/Makefile.inc +++ b/src/soc/amd/genoa/Makefile.inc @@ -14,8 +14,12 @@ romstage-y += romstage.c ramstage-y += aoac.c ramstage-y += chip.c +ramstage-y += cpu.c ramstage-y += domain.c ramstage-y += root_complex.c +ramstage-y += smihandler.c + +smm-y += smihandler.c CPPFLAGS_common += -I$(src)/soc/amd/genoa/include diff --git a/src/soc/amd/genoa/chipset.cb b/src/soc/amd/genoa/chipset.cb index e2d0e2ec85..58c11561a5 100644 --- a/src/soc/amd/genoa/chipset.cb +++ b/src/soc/amd/genoa/chipset.cb @@ -1,8 +1,7 @@ # SPDX-License-Identifier: GPL-2.0-only chip soc/amd/genoa - device cpu_cluster 0 on - end + device cpu_cluster 0 on ops amd_cpu_bus_ops end device domain 0 on ops genoa_pci_domain_ops diff --git a/src/soc/amd/genoa/cpu.c b/src/soc/amd/genoa/cpu.c new file mode 100644 index 0000000000..8a7d8e9245 --- /dev/null +++ b/src/soc/amd/genoa/cpu.c @@ -0,0 +1,26 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#include <amdblocks/cpu.h> +#include <cpu/cpu.h> +#include <device/device.h> +#include <soc/cpu.h> + +static void model_19_init(struct device *dev) +{ + set_cstate_io_addr(); +} + +static struct device_operations cpu_dev_ops = { + .init = model_19_init, +}; + +static struct cpu_device_id cpu_table[] = { + { X86_VENDOR_AMD, GENOA_A0_CPUID, CPUID_ALL_STEPPINGS_MASK }, + { X86_VENDOR_AMD, GENOA_B0_CPUID, CPUID_ALL_STEPPINGS_MASK }, + CPU_TABLE_END +}; + +static const struct cpu_driver model_19 __cpu_driver = { + .ops = &cpu_dev_ops, + .id_table = cpu_table, +}; diff --git a/src/soc/amd/genoa/include/soc/cpu.h b/src/soc/amd/genoa/include/soc/cpu.h new file mode 100644 index 0000000000..836c9877ba --- /dev/null +++ b/src/soc/amd/genoa/include/soc/cpu.h @@ -0,0 +1,9 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ + +#ifndef AMD_GENOA_CPU_H +#define AMD_GENOA_CPU_H + +#define GENOA_A0_CPUID CPUID_FROM_FMS(0x19, 0x10, 0) +#define GENOA_B0_CPUID CPUID_FROM_FMS(0x19, 0x11, 0) + +#endif /* AMD_GENOA_CPU_H */ diff --git a/src/soc/amd/genoa/smihandler.c b/src/soc/amd/genoa/smihandler.c new file mode 100644 index 0000000000..4d93baa408 --- /dev/null +++ b/src/soc/amd/genoa/smihandler.c @@ -0,0 +1,96 @@ +/* SPDX-License-Identifier: GPL-2.0-or-later */ + +#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> + +/* + * Both the psp_notify_sx_info and the smu_sx_entry call will clobber the SMN index register + * during the SMN accesses. Since the SMI handler is the last thing that gets called before + * entering S3, this won't interfere with any indirect SMN accesses via the same register pair. + */ +static void fch_slp_typ_handler(void) +{ + uint32_t pci_ctrl; + uint16_t pm1cnt; + 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); + + smu_sx_entry(); /* Leave SlpTypeEn clear, SMU will set */ + printk(BIOS_ERR, "System did not go to sleep\n"); + hlt(); + } +} + +/* + * 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; +} |