diff options
author | Marshall Dawson <marshall.dawson@amd.corp-partner.google.com> | 2020-03-05 11:44:24 -0700 |
---|---|---|
committer | Felix Held <felix-coreboot@felixheld.de> | 2020-04-13 12:39:12 +0000 |
commit | d6b7236732d8cc74545849f4b81af1d33e8758e2 (patch) | |
tree | 8203c3ad9d18a49d4bc243e0bdbe02b0fad77be0 /src/soc/amd/common/block/psp/psp_gen2.c | |
parent | a67c753d554c730c794726b1b65d07c9c383e264 (diff) | |
download | coreboot-d6b7236732d8cc74545849f4b81af1d33e8758e2.tar.xz |
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.c | 104 |
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; +} |