summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/soc/amd/common/block/include/amdblocks/psp.h14
-rw-r--r--src/soc/amd/common/block/psp/Kconfig12
-rw-r--r--src/soc/amd/common/block/psp/psp.c57
3 files changed, 83 insertions, 0 deletions
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/<codename> 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 <arch/io.h>
+#include <cbfs.h>
+#include <region_file.h>
#include <timer.h>
#include <device/pci_def.h>
#include <console/console.h>
@@ -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;
+}