aboutsummaryrefslogtreecommitdiff
path: root/src/soc/amd/common/block/psp/psp_gen2.c
diff options
context:
space:
mode:
authorMarshall Dawson <marshall.dawson@amd.corp-partner.google.com>2020-03-05 11:44:24 -0700
committerFelix Held <felix-coreboot@felixheld.de>2020-04-13 12:39:12 +0000
commitd6b7236732d8cc74545849f4b81af1d33e8758e2 (patch)
tree8203c3ad9d18a49d4bc243e0bdbe02b0fad77be0 /src/soc/amd/common/block/psp/psp_gen2.c
parenta67c753d554c730c794726b1b65d07c9c383e264 (diff)
soc/amd/common/psp: Split mailbox support into v1 and v2
Family 17h redefines the PSP command and status, and therefore the steps required to send commands via the mailbox. Convert the existing version into a v1 and add a v2. New Kconfig options allow the soc to choose v1 vs. v2. The v2 PSP begins responding to the mailbox command when the full bit range is written. Define the new mailbox as a union of a u32 and a structure. Additional PSP details may be found in the NDA publication (#55758) AMD Platform Security Processor BIOS Architecture Design Guide for AMD Family 17h Processors Change the existing two soc functions that return pointers to void pointers. BUG=b:153677737 Signed-off-by: Marshall Dawson <marshalldawson3rd@gmail.com> Signed-off-by: Felix Held <felix-coreboot@felixheld.de> Change-Id: I4d358fdae07da471640856f57568059e9487f6a8 Reviewed-on: https://review.coreboot.org/c/coreboot/+/40293 Tested-by: build bot (Jenkins) <no-reply@coreboot.org> Reviewed-by: Angel Pons <th3fanbus@gmail.com>
Diffstat (limited to 'src/soc/amd/common/block/psp/psp_gen2.c')
-rw-r--r--src/soc/amd/common/block/psp/psp_gen2.c104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/soc/amd/common/block/psp/psp_gen2.c b/src/soc/amd/common/block/psp/psp_gen2.c
new file mode 100644
index 0000000000..b70babc14a
--- /dev/null
+++ b/src/soc/amd/common/block/psp/psp_gen2.c
@@ -0,0 +1,104 @@
+/* SPDX-License-Identifier: GPL-2.0-only */
+/* This file is part of the coreboot project. */
+
+#include <device/mmio.h>
+#include <timer.h>
+#include <bootstate.h>
+#include <amdblocks/psp.h>
+#include <soc/iomap.h>
+#include <soc/northbridge.h>
+#include "psp_def.h"
+
+static u16 rd_mbox_sts(struct pspv2_mbox *mbox)
+{
+ union {
+ u32 val;
+ struct pspv2_mbox_cmd_fields fields;
+ } tmp = { 0 };
+
+ tmp.val = read32(&mbox->val);
+ return tmp.fields.mbox_status;
+}
+
+static void wr_mbox_cmd(struct pspv2_mbox *mbox, u8 cmd)
+{
+ union {
+ u32 val;
+ struct pspv2_mbox_cmd_fields fields;
+ } tmp = { 0 };
+
+ /* Write entire 32-bit area to begin command execution */
+ tmp.fields.mbox_command = cmd;
+ write32(&mbox->val, tmp.val);
+}
+
+static u8 rd_mbox_recovery(struct pspv2_mbox *mbox)
+{
+ union {
+ u32 val;
+ struct pspv2_mbox_cmd_fields fields;
+ } tmp = { 0 };
+
+ tmp.val = read32(&mbox->val);
+ return !!tmp.fields.recovery;
+}
+
+static void wr_mbox_cmd_resp(struct pspv2_mbox *mbox, void *buffer)
+{
+ write64(&mbox->cmd_response, (uintptr_t)buffer);
+}
+
+static int wait_command(struct pspv2_mbox *mbox, bool wait_for_ready)
+{
+ struct pspv2_mbox and_mask = { .val = ~0 };
+ struct pspv2_mbox expected = { .val = 0 };
+ struct stopwatch sw;
+ u32 tmp;
+
+ /* Zero fields from and_mask that should be kept */
+ and_mask.fields.mbox_command = 0;
+ and_mask.fields.ready = wait_for_ready ? 0 : 1;
+
+ /* Expect mbox_cmd == 0 but ready depends */
+ if (wait_for_ready)
+ expected.fields.ready = 1;
+
+ stopwatch_init_msecs_expire(&sw, PSP_CMD_TIMEOUT);
+
+ do {
+ tmp = read32(&mbox->val);
+ tmp &= ~and_mask.val;
+ if (tmp == expected.val)
+ return 0;
+ } while (!stopwatch_expired(&sw));
+
+ return -PSPSTS_CMD_TIMEOUT;
+}
+
+int send_psp_command(u32 command, void *buffer)
+{
+ struct pspv2_mbox *mbox = soc_get_mbox_address();
+ if (!mbox)
+ return -PSPSTS_NOBASE;
+
+ if (rd_mbox_recovery(mbox))
+ return -PSPSTS_RECOVERY;
+
+ if (wait_command(mbox, true))
+ return -PSPSTS_CMD_TIMEOUT;
+
+ /* set address of command-response buffer and write command register */
+ wr_mbox_cmd_resp(mbox, buffer);
+ wr_mbox_cmd(mbox, command);
+
+ /* PSP clears command register when complete. All commands except
+ * SxInfo set the Ready bit. */
+ if (wait_command(mbox, command != MBOX_BIOS_CMD_SX_INFO))
+ return -PSPSTS_CMD_TIMEOUT;
+
+ /* check delivery status */
+ if (rd_mbox_sts(mbox))
+ return -PSPSTS_SEND_ERROR;
+
+ return 0;
+}