diff --git a/src/soc/amd/common/block/psp/Kconfig b/src/soc/amd/common/block/psp/Kconfig index 7ef7e40b3b..3249174adb 100644 --- a/src/soc/amd/common/block/psp/Kconfig +++ b/src/soc/amd/common/block/psp/Kconfig @@ -35,3 +35,11 @@ config AMD_SOC_SEPARATE_EFS_SECTION FMAP section must begin exactly at the location the EFS needs to be placed in the flash. This option can be used to place the EFS right after the 128kByte EC firmware at the beginning of the flash. + +config SOC_AMD_COMMON_BLOCK_PSP_FUSE_SPL + bool + default n + depends on SOC_AMD_COMMON_BLOCK_PSP_GEN2 + help + Enable sending of set SPL message to PSP. Enable this option if the platform + will require SPL fusing to be performed by PSP. diff --git a/src/soc/amd/common/block/psp/psp_def.h b/src/soc/amd/common/block/psp/psp_def.h index 5baa0642dc..11686aab22 100644 --- a/src/soc/amd/common/block/psp/psp_def.h +++ b/src/soc/amd/common/block/psp/psp_def.h @@ -17,12 +17,18 @@ #define MBOX_BIOS_CMD_CLEAR_S3_STS 0x07 #define MBOX_BIOS_CMD_S3_DATA_INFO 0x08 #define MBOX_BIOS_CMD_NOP 0x09 +#define MBOX_BIOS_CMD_SET_SPL_FUSE 0x2d +#define MBOX_BIOS_CMD_QUERY_SPL_FUSE 0x47 #define MBOX_BIOS_CMD_ABORT 0xfe + /* x86 to PSP commands, v1-only */ #define MBOX_BIOS_CMD_DRAM_INFO 0x01 #define MBOX_BIOS_CMD_SMU_FW 0x19 #define MBOX_BIOS_CMD_SMU_FW2 0x1a +#define CORE_2_PSP_MSG_38_OFFSET 0x10998 +#define CORE_2_PSP_MSG_38_FUSE_SPL BIT(12) + /* generic PSP interface status, v1 */ #define PSPV1_STATUS_INITIALIZED BIT(0) #define PSPV1_STATUS_ERROR BIT(1) @@ -102,6 +108,11 @@ struct mbox_cmd_sx_info_buffer { u8 sleep_type; } __attribute__((packed, aligned(32))); +struct mbox_cmd_late_spl_buffer { + struct mbox_buffer_header header; + uint32_t spl_value; +} __attribute__((packed, aligned(32))); + #define PSP_INIT_TIMEOUT 10000 /* 10 seconds */ #define PSP_CMD_TIMEOUT 1000 /* 1 second */ @@ -110,4 +121,6 @@ void psp_print_cmd_status(int cmd_status, struct mbox_buffer_header *header); /* This command needs to be implemented by the generation specific code. */ int send_psp_command(u32 command, void *buffer); +enum cb_err soc_read_c2p38(uint32_t *msg_38_value); + #endif /* __AMD_PSP_DEF_H__ */ diff --git a/src/soc/amd/common/block/psp/psp_gen2.c b/src/soc/amd/common/block/psp/psp_gen2.c index aef7dad767..e5f23cd5b1 100644 --- a/src/soc/amd/common/block/psp/psp_gen2.c +++ b/src/soc/amd/common/block/psp/psp_gen2.c @@ -1,5 +1,6 @@ /* SPDX-License-Identifier: GPL-2.0-only */ +#include #include #include #include @@ -120,3 +121,44 @@ int send_psp_command(u32 command, void *buffer) return 0; } + +enum cb_err soc_read_c2p38(uint32_t *msg_38_value) +{ + uintptr_t psp_mmio = soc_get_psp_base_address(); + + if (!psp_mmio) { + printk(BIOS_WARNING, "PSP: PSP_ADDR_MSR uninitialized\n"); + return CB_ERR; + } + *msg_38_value = read32((void *)psp_mmio + CORE_2_PSP_MSG_38_OFFSET); + return CB_SUCCESS; +} + +static void psp_set_spl_fuse(void *unused) +{ + if (!CONFIG(SOC_AMD_COMMON_BLOCK_PSP_FUSE_SPL)) + return; + + uint32_t msg_38_value = 0; + int cmd_status = 0; + struct mbox_cmd_late_spl_buffer buffer = { + .header = { + .size = sizeof(buffer) + } + }; + + if (soc_read_c2p38(&msg_38_value) != CB_SUCCESS) { + printk(BIOS_ERR, "PSP: Failed to read psp base address.\n"); + return; + } + + if (msg_38_value & CORE_2_PSP_MSG_38_FUSE_SPL) { + printk(BIOS_DEBUG, "PSP: Fuse SPL requested\n"); + cmd_status = send_psp_command(MBOX_BIOS_CMD_SET_SPL_FUSE, &buffer); + psp_print_cmd_status(cmd_status, NULL); + } else { + printk(BIOS_DEBUG, "PSP: Fuse SPL not requested\n"); + } +} + +BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, psp_set_spl_fuse, NULL);