From 596ecec009d722aebbfc16074b89bc78dc9ede26 Mon Sep 17 00:00:00 2001 From: Marshall Dawson Date: Thu, 12 Oct 2017 16:04:08 -0600 Subject: soc/amd/common/psp: Add command to load fw blobs An upcoming PSP firmware change will allow coreboot to load the two SMU firmware blobs (one runs in SRAM and the other in DRAM). The traditional method is for the PSP to control most of the process, e.g. loading the SRAM version prior to releasing the x86 reset. Add a new command that can instruct the PSP to load a firmware blob from a location in the flash. The definition for commands 19 and 1a differ from others in that they do not use a command/response buffer. Instead, the PSP will look in the command/response pointer registers directly for the blob's address. BUG=b:66339938 Change-Id: I8431af341930f45ac74f471628b4dc4ede7735f4 Signed-off-by: Marshall Dawson Reviewed-on: https://review.coreboot.org/22056 Tested-by: build bot (Jenkins) Reviewed-by: Aaron Durbin --- src/soc/amd/common/block/include/amdblocks/psp.h | 14 ++++++ src/soc/amd/common/block/psp/Kconfig | 12 +++++ src/soc/amd/common/block/psp/psp.c | 57 ++++++++++++++++++++++++ 3 files changed, 83 insertions(+) diff --git a/src/soc/amd/common/block/include/amdblocks/psp.h b/src/soc/amd/common/block/include/amdblocks/psp.h index d210498502..74ea73f7f7 100644 --- a/src/soc/amd/common/block/include/amdblocks/psp.h +++ b/src/soc/amd/common/block/include/amdblocks/psp.h @@ -32,6 +32,8 @@ #define MBOX_BIOS_CMD_CLEAR_S3_STS 0x07 #define MBOX_BIOS_CMD_C3_DATA_INFO 0x08 #define MBOX_BIOS_CMD_NOP 0x09 +#define MBOX_BIOS_CMD_SMU_FW 0x19 +#define MBOX_BIOS_CMD_SMU_FW2 0x1a #define MBOX_BIOS_CMD_ABORT 0xfe /* generic PSP interface status */ @@ -79,11 +81,23 @@ struct mbox_default_buffer { /* command-response buffer unused by command */ #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 PSP_INIT_TIMEOUT 10000 /* 10 seconds */ #define PSP_CMD_TIMEOUT 1000 /* 1 second */ /* BIOS-to-PSP functions return 0 if successful, else negative value */ + int psp_notify_dram(void); +/* + * type: identical to the corresponding PSP command, e.g. pass + * MBOX_BIOS_CMD_SMU_FW2 to load SMU FW2 blob. + * name: cbfs file name + */ +int psp_load_named_blob(int type, const char *name); + #endif /* __AMD_PSP_H__ */ diff --git a/src/soc/amd/common/block/psp/Kconfig b/src/soc/amd/common/block/psp/Kconfig index 69958f21aa..0517a2f33f 100644 --- a/src/soc/amd/common/block/psp/Kconfig +++ b/src/soc/amd/common/block/psp/Kconfig @@ -4,3 +4,15 @@ config SOC_AMD_COMMON_BLOCK_PSP help This option builds in the Platform Security Processor initialization functions. + +config SOC_AMD_PSP_SELECTABLE_SMU_FW + bool + default n + help + Some PSP implementations allow storing SMU firmware into cbfs and + calling the PSP to load the blobs at the proper time. + + The soc/ should select this if its PSP supports the feature + and each mainboard can choose to select an appropriate fanless or + fanned set of blobs. Ask your AMD representative whether your APU + is considered fanless. diff --git a/src/soc/amd/common/block/psp/psp.c b/src/soc/amd/common/block/psp/psp.c index 8b3605e6fa..5aedfc138f 100644 --- a/src/soc/amd/common/block/psp/psp.c +++ b/src/soc/amd/common/block/psp/psp.c @@ -14,6 +14,8 @@ */ #include +#include +#include #include #include #include @@ -199,3 +201,58 @@ int psp_notify_dram(void) return cmd_status; } + +/* + * Tell the PSP to load a firmware blob from a location in the BIOS image. + */ +static int psp_load_blob(int type, void *addr) +{ + int cmd_status; + + if (!IS_ENABLED(CONFIG_SOC_AMD_PSP_SELECTABLE_SMU_FW)) { + printk(BIOS_ERR, "BUG: Selectable firmware is not supported\n"); + return PSPSTS_UNSUPPORTED; + } + + /* only two types currently supported */ + if (type != MBOX_BIOS_CMD_SMU_FW && type != MBOX_BIOS_CMD_SMU_FW2) { + printk(BIOS_ERR, "BUG: Invalid PSP blob type %x\n", type); + return PSPSTS_INVALID_BLOB; + } + + printk(BIOS_DEBUG, "PSP: Load blob type %x from @%p... ", type, addr); + + /* Blob commands use the buffer registers as data, not pointer to buf */ + cmd_status = send_psp_command(type, addr); + + if (cmd_status) + printk(BIOS_DEBUG, "%s\n", status_to_string(cmd_status)); + else + printk(BIOS_DEBUG, "OK\n"); + + return cmd_status; +} + +int psp_load_named_blob(int type, const char *name) +{ + void *blob; + struct cbfsf cbfs_file; + struct region_device rdev; + int r; + + if (cbfs_boot_locate(&cbfs_file, name, NULL)) { + printk(BIOS_ERR, "BUG: Cannot locate blob for PSP loading\n"); + return PSPSTS_INVALID_NAME; + } + + cbfs_file_data(&rdev, &cbfs_file); + blob = rdev_mmap_full(&rdev); + if (blob) { + r = psp_load_blob(type, blob); + rdev_munmap(&rdev, blob); + } else { + printk(BIOS_ERR, "BUG: Cannot map blob for PSP loading\n"); + return PSPSTS_INVALID_NAME; + } + return r; +} -- cgit v1.2.3