diff options
-rw-r--r-- | src/soc/amd/common/block/include/amdblocks/psp.h | 55 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/Makefile.inc | 1 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_def.h | 19 | ||||
-rw-r--r-- | src/soc/amd/common/block/psp/psp_smm.c | 78 | ||||
-rw-r--r-- | src/soc/amd/picasso/include/soc/smi.h | 3 | ||||
-rw-r--r-- | src/soc/amd/picasso/psp.c | 39 | ||||
-rw-r--r-- | src/soc/amd/picasso/smi.c | 3 | ||||
-rw-r--r-- | src/soc/amd/picasso/smihandler.c | 4 |
8 files changed, 192 insertions, 10 deletions
diff --git a/src/soc/amd/common/block/include/amdblocks/psp.h b/src/soc/amd/common/block/include/amdblocks/psp.h index 53946fb8d2..a1c1152af9 100644 --- a/src/soc/amd/common/block/include/amdblocks/psp.h +++ b/src/soc/amd/common/block/include/amdblocks/psp.h @@ -7,21 +7,56 @@ /* Get the mailbox base address - specific to family of device. */ void *soc_get_mbox_address(void); +#define SMM_TRIGGER_IO 0 +#define SMM_TRIGGER_MEM 1 + +#define SMM_TRIGGER_BYTE 0 +#define SMM_TRIGGER_WORD 1 +#define SMM_TRIGGER_DWORD 2 + +struct smm_trigger_info { + uint64_t address; /* Memory or IO address */ + uint32_t address_type; /* 0=I/O, 1=memory */ + uint32_t value_width; /* 0=byte, 1=word, 2=qword */ + uint32_t value_and_mask; + uint32_t value_or_mask; +} __packed; + +struct smm_register { + uint64_t address; /* Memory or IO address */ + uint32_t address_type; /* 0=I/O, 1=memory */ + uint32_t value_width; /* 0=byte, 1=word, 2=qword */ + uint32_t reg_bit_mask; + uint32_t expect_value; +} __packed; + +struct smm_register_info { + struct smm_register smi_enb; + struct smm_register eos; + struct smm_register psp_smi_en; + struct smm_register reserved[5]; +} __packed; + +void soc_fill_smm_trig_info(struct smm_trigger_info *trig); +void soc_fill_smm_reg_info(struct smm_register_info *reg); /* v2 only */ + /* BIOS-to-PSP functions return 0 if successful, else negative value */ -#define PSPSTS_SUCCESS 0 -#define PSPSTS_NOBASE 1 -#define PSPSTS_HALTED 2 -#define PSPSTS_RECOVERY 3 -#define PSPSTS_SEND_ERROR 4 -#define PSPSTS_INIT_TIMEOUT 5 -#define PSPSTS_CMD_TIMEOUT 6 +#define PSPSTS_SUCCESS 0 +#define PSPSTS_NOBASE 1 +#define PSPSTS_HALTED 2 +#define PSPSTS_RECOVERY 3 +#define PSPSTS_SEND_ERROR 4 +#define PSPSTS_INIT_TIMEOUT 5 +#define PSPSTS_CMD_TIMEOUT 6 /* other error codes */ -#define PSPSTS_UNSUPPORTED 7 -#define PSPSTS_INVALID_NAME 8 -#define PSPSTS_INVALID_BLOB 9 +#define PSPSTS_UNSUPPORTED 7 +#define PSPSTS_INVALID_NAME 8 +#define PSPSTS_INVALID_BLOB 9 int psp_notify_dram(void); +int psp_notify_smm(void); + /* * type: identical to the corresponding PSP command, e.g. pass * MBOX_BIOS_CMD_SMU_FW2 to load SMU FW2 blob. diff --git a/src/soc/amd/common/block/psp/Makefile.inc b/src/soc/amd/common/block/psp/Makefile.inc index dc9a385e39..c2a33354ad 100644 --- a/src/soc/amd/common/block/psp/Makefile.inc +++ b/src/soc/amd/common/block/psp/Makefile.inc @@ -11,5 +11,6 @@ ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN1) += psp_gen1.c ramstage-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2) += psp_gen2.c smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp.c +smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP) += psp_smm.c smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN1) += psp_gen1.c smm-$(CONFIG_SOC_AMD_COMMON_BLOCK_PSP_GEN2) += psp_gen2.c diff --git a/src/soc/amd/common/block/psp/psp_def.h b/src/soc/amd/common/block/psp/psp_def.h index f3ac5c2181..63ca3abb0a 100644 --- a/src/soc/amd/common/block/psp/psp_def.h +++ b/src/soc/amd/common/block/psp/psp_def.h @@ -6,6 +6,7 @@ #include <types.h> #include <commonlib/helpers.h> +#include <amdblocks/psp.h> /* x86 to PSP commands */ #define MBOX_BIOS_CMD_DRAM_INFO 0x01 @@ -81,6 +82,24 @@ struct mbox_default_buffer { /* command-response buffer unused by command */ struct mbox_buffer_header header; } __attribute__((packed, aligned(32))); +struct smm_req_buffer { + uint64_t smm_base; /* TSEG base */ + uint64_t smm_mask; /* TSEG mask */ + uint64_t psp_smm_data_region; /* PSP region in SMM space */ + uint64_t psp_smm_data_length; /* PSP region length in SMM space */ + struct smm_trigger_info smm_trig_info; +#if CONFIG(SOC_AMD_COMMON_BLOCK_PSP_GEN2) + struct smm_register_info smm_reg_info; +#endif + uint64_t psp_mbox_smm_buffer_address; + uint64_t psp_mbox_smm_flag_address; +} __packed; + +struct mbox_cmd_smm_info_buffer { + struct mbox_buffer_header header; + struct smm_req_buffer req; +} __attribute__((packed, aligned(32))); + struct mbox_cmd_sx_info_buffer { struct mbox_buffer_header header; u8 sleep_type; diff --git a/src/soc/amd/common/block/psp/psp_smm.c b/src/soc/amd/common/block/psp/psp_smm.c new file mode 100644 index 0000000000..cc15738881 --- /dev/null +++ b/src/soc/amd/common/block/psp/psp_smm.c @@ -0,0 +1,78 @@ +/* SPDX-License-Identifier: GPL-2.0-only */ +/* This file is part of the coreboot project. */ + +#include <device/mmio.h> +#include <cpu/x86/msr.h> +#include <cpu/amd/msr.h> +#include <cbfs.h> +#include <region_file.h> +#include <timer.h> +#include <bootstate.h> +#include <rules.h> +#include <console/console.h> +#include <amdblocks/psp.h> +#include <soc/iomap.h> +#include <soc/northbridge.h> +#include "psp_def.h" + +#define C2P_BUFFER_MAXSIZE 0xc00 /* Core-to-PSP buffer */ +#define P2C_BUFFER_MAXSIZE 0xc00 /* PSP-to-core buffer */ + +struct { + u8 buffer[C2P_BUFFER_MAXSIZE]; +} __attribute__((aligned(32))) c2p_buffer; + +struct { + u8 buffer[P2C_BUFFER_MAXSIZE]; +} __attribute__((aligned(32))) p2c_buffer; + +static uint32_t smm_flag; /* Non-zero for SMM, clear when not */ + +static void set_smm_flag(void) +{ + smm_flag = 1; +} + +static void clear_smm_flag(void) +{ + smm_flag = 0; +} + +int psp_notify_smm(void) +{ + msr_t msr; + int cmd_status; + struct mbox_cmd_smm_info_buffer buffer = { + .header = { + .size = sizeof(buffer) + }, + .req = { + .psp_smm_data_region = (uintptr_t)p2c_buffer.buffer, + .psp_smm_data_length = sizeof(p2c_buffer), + .psp_mbox_smm_buffer_address = (uintptr_t)c2p_buffer.buffer, + .psp_mbox_smm_flag_address = (uintptr_t)&smm_flag, + } + }; + + msr = rdmsr(SMM_ADDR_MSR); + buffer.req.smm_base = ((uint64_t)msr.hi << 32) | msr.lo; + msr = rdmsr(SMM_MASK_MSR); + msr.lo &= 0xffff0000; /* mask SMM_LOCK and SMM_TSEG_VALID and reserved bits */ + buffer.req.smm_mask = ((uint64_t)msr.hi << 32) | msr.lo; + + soc_fill_smm_trig_info(&buffer.req.smm_trig_info); +#if (CONFIG(SOC_AMD_COMMON_BLOCK_PSP_GEN2)) + soc_fill_smm_reg_info(&buffer.req.smm_reg_info); +#endif + + printk(BIOS_DEBUG, "PSP: Notify SMM info... "); + + set_smm_flag(); + cmd_status = send_psp_command(MBOX_BIOS_CMD_SMM_INFO, &buffer); + clear_smm_flag(); + + /* buffer's status shouldn't change but report it if it does */ + psp_print_cmd_status(cmd_status, (struct mbox_default_buffer *)&buffer); + + return cmd_status; +} diff --git a/src/soc/amd/picasso/include/soc/smi.h b/src/soc/amd/picasso/include/soc/smi.h index e890e1319a..fb8061ca16 100644 --- a/src/soc/amd/picasso/include/soc/smi.h +++ b/src/soc/amd/picasso/include/soc/smi.h @@ -86,6 +86,7 @@ #define SMITYPE_NB_GPP_HOT_PLUG 30 /* 31 Reserved */ #define SMITYPE_WAKE_L2 32 +#define SMITYPE_PSP 33 /* 33 - 38 Reserved */ #define SMITYPE_AZPME 39 #define SMITYPE_USB_PD_I2C4 40 @@ -186,6 +187,8 @@ #define SMI_REG_CONTROL8 0xc0 #define SMI_REG_CONTROL9 0xc4 +#define SMI_MODE_MASK 0x03 + enum smi_mode { SMI_MODE_DISABLE = 0, SMI_MODE_SMI = 1, diff --git a/src/soc/amd/picasso/psp.c b/src/soc/amd/picasso/psp.c index d6eb7d31a3..88b25b88b0 100644 --- a/src/soc/amd/picasso/psp.c +++ b/src/soc/amd/picasso/psp.c @@ -3,6 +3,8 @@ #include <console/console.h> #include <cpu/x86/msr.h> +#include <soc/smi.h> +#include <amdblocks/acpimmio_map.h> #include <amdblocks/psp.h> #define PSP_MAILBOX_OFFSET 0x10570 @@ -20,3 +22,40 @@ void *soc_get_mbox_address(void) return (void *)(psp_mmio + PSP_MAILBOX_OFFSET); } + +void soc_fill_smm_trig_info(struct smm_trigger_info *trig) +{ + if (!trig) + return; + + trig->address = 0xfed802a8; + trig->address_type = SMM_TRIGGER_MEM; + trig->value_width = SMM_TRIGGER_DWORD; + trig->value_and_mask = 0xfdffffff; + trig->value_or_mask = 0x02000000; +} + +void soc_fill_smm_reg_info(struct smm_register_info *reg) +{ + if (!reg) + return; + + reg->smi_enb.address = ACPIMMIO_SMI_BASE + SMI_REG_SMITRIG0; + reg->smi_enb.address_type = SMM_TRIGGER_MEM; + reg->smi_enb.value_width = SMM_TRIGGER_DWORD; + reg->smi_enb.reg_bit_mask = SMITRG0_SMIENB; + reg->smi_enb.expect_value = 0; + + reg->eos.address = ACPIMMIO_SMI_BASE + SMI_REG_SMITRIG0; + reg->eos.address_type = SMM_TRIGGER_MEM; + reg->eos.value_width = SMM_TRIGGER_DWORD; + reg->eos.reg_bit_mask = SMITRG0_EOS; + reg->eos.expect_value = SMITRG0_EOS; + + reg->psp_smi_en.address = ACPIMMIO_SMI_BASE + SMI_REG_CONTROL0; + reg->psp_smi_en.address += sizeof(uint32_t) * SMITYPE_PSP / 16; + reg->psp_smi_en.address_type = SMM_TRIGGER_MEM; + reg->psp_smi_en.value_width = SMM_TRIGGER_DWORD; + reg->psp_smi_en.reg_bit_mask = SMI_MODE_MASK << (2 * SMITYPE_PSP % 16); + reg->psp_smi_en.expect_value = SMI_MODE_SMI << (2 * SMITYPE_PSP % 16); +} diff --git a/src/soc/amd/picasso/smi.c b/src/soc/amd/picasso/smi.c index ab8f405e59..273c55b635 100644 --- a/src/soc/amd/picasso/smi.c +++ b/src/soc/amd/picasso/smi.c @@ -17,6 +17,7 @@ * Utilities for SMM setup */ +#include <arch/io.h> #include <console/console.h> #include <cpu/x86/smm.h> #include <amdblocks/acpimmio.h> @@ -35,4 +36,6 @@ void enable_smi_generation(void) reg &= ~SMITRG0_SMIENB; /* Enable SMI generation */ reg |= SMITRG0_EOS; /* Set EOS bit */ smi_write32(SMI_REG_SMITRIG0, reg); + + outb(APM_CNT_SMMINFO, APM_CNT); } diff --git a/src/soc/amd/picasso/smihandler.c b/src/soc/amd/picasso/smihandler.c index 55493776dd..e4d1c86f57 100644 --- a/src/soc/amd/picasso/smihandler.c +++ b/src/soc/amd/picasso/smihandler.c @@ -26,6 +26,7 @@ #include <soc/southbridge.h> #include <amdblocks/acpimmio.h> #include <amdblocks/acpi.h> +#include <amdblocks/psp.h> #include <elog.h> /* bits in smm_io_trap */ @@ -125,6 +126,9 @@ static void sb_apmc_smi_handler(void) if (CONFIG(SMMSTORE)) southbridge_smi_store(); break; + case APM_CNT_SMMINFO: + psp_notify_smm(); + break; } mainboard_smi_apmc(cmd); |