coreboot
coreboot is an Open Source project aimed at replacing the proprietary BIOS found in most computers.
psp_gen2.c
Go to the documentation of this file.
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 
3 #include <bootstate.h>
4 #include <console/console.h>
5 #include <cpu/amd/msr.h>
6 #include <cpu/x86/msr.h>
7 #include <device/mmio.h>
8 #include <timer.h>
9 #include <amdblocks/psp.h>
10 #include <soc/iomap.h>
11 #include "psp_def.h"
12 
13 #define PSP_MAILBOX_COMMAND_OFFSET 0x10570 /* 4 bytes */
14 #define PSP_MAILBOX_BUFFER_OFFSET 0x10574 /* 8 bytes */
15 
25 };
26 
28 {
29  uintptr_t psp_mmio = rdmsr(PSP_ADDR_MSR).lo;
30  if (!psp_mmio)
31  printk(BIOS_ERR, "PSP: PSP_ADDR_MSR uninitialized\n");
32  return psp_mmio;
33 }
34 
35 static u16 rd_mbox_sts(uintptr_t psp_mmio)
36 {
37  union pspv2_mbox_command tmp;
38 
39  tmp.val = read32p(psp_mmio + PSP_MAILBOX_COMMAND_OFFSET);
40  return tmp.fields.mbox_status;
41 }
42 
43 static void wr_mbox_cmd(uintptr_t psp_mmio, u8 cmd)
44 {
45  union pspv2_mbox_command tmp = { .val = 0 };
46 
47  /* Write entire 32-bit area to begin command execution */
48  tmp.fields.mbox_command = cmd;
49  write32p(psp_mmio + PSP_MAILBOX_COMMAND_OFFSET, tmp.val);
50 }
51 
52 static u8 rd_mbox_recovery(uintptr_t psp_mmio)
53 {
54  union pspv2_mbox_command tmp;
55 
56  tmp.val = read32p(psp_mmio + PSP_MAILBOX_COMMAND_OFFSET);
57  return !!tmp.fields.recovery;
58 }
59 
60 static void wr_mbox_buffer_ptr(uintptr_t psp_mmio, void *buffer)
61 {
63 }
64 
65 static int wait_command(uintptr_t psp_mmio, bool wait_for_ready)
66 {
67  union pspv2_mbox_command and_mask = { .val = ~0 };
68  union pspv2_mbox_command expected = { .val = 0 };
69  struct stopwatch sw;
70  u32 tmp;
71 
72  /* Zero fields from and_mask that should be kept */
73  and_mask.fields.mbox_command = 0;
74  and_mask.fields.ready = wait_for_ready ? 0 : 1;
75 
76  /* Expect mbox_cmd == 0 but ready depends */
77  if (wait_for_ready)
78  expected.fields.ready = 1;
79 
81 
82  do {
83  tmp = read32p(psp_mmio + PSP_MAILBOX_COMMAND_OFFSET);
84  tmp &= ~and_mask.val;
85  if (tmp == expected.val)
86  return 0;
87  } while (!stopwatch_expired(&sw));
88 
89  return -PSPSTS_CMD_TIMEOUT;
90 }
91 
92 int send_psp_command(u32 command, void *buffer)
93 {
95  if (!psp_mmio)
96  return -PSPSTS_NOBASE;
97 
98  if (rd_mbox_recovery(psp_mmio))
99  return -PSPSTS_RECOVERY;
100 
101  if (wait_command(psp_mmio, true))
102  return -PSPSTS_CMD_TIMEOUT;
103 
104  /* set address of command-response buffer and write command register */
105  wr_mbox_buffer_ptr(psp_mmio, buffer);
106  wr_mbox_cmd(psp_mmio, command);
107 
108  /* PSP clears command register when complete. All commands except
109  * SxInfo set the Ready bit. */
110  if (wait_command(psp_mmio, command != MBOX_BIOS_CMD_SX_INFO))
111  return -PSPSTS_CMD_TIMEOUT;
112 
113  /* check delivery status */
114  if (rd_mbox_sts(psp_mmio))
115  return -PSPSTS_SEND_ERROR;
116 
117  return 0;
118 }
119 
120 enum cb_err soc_read_c2p38(uint32_t *msg_38_value)
121 {
122  uintptr_t psp_mmio = soc_get_psp_base_address();
123 
124  if (!psp_mmio) {
125  printk(BIOS_WARNING, "PSP: PSP_ADDR_MSR uninitialized\n");
126  return CB_ERR;
127  }
128  *msg_38_value = read32p(psp_mmio + CORE_2_PSP_MSG_38_OFFSET);
129  return CB_SUCCESS;
130 }
131 
132 static void psp_set_spl_fuse(void *unused)
133 {
134  if (!CONFIG(SOC_AMD_COMMON_BLOCK_PSP_FUSE_SPL))
135  return;
136 
137  uint32_t msg_38_value = 0;
138  int cmd_status = 0;
140  .header = {
141  .size = sizeof(buffer)
142  }
143  };
144 
145  if (soc_read_c2p38(&msg_38_value) != CB_SUCCESS) {
146  printk(BIOS_ERR, "PSP: Failed to read psp base address.\n");
147  return;
148  }
149 
150  if (msg_38_value & CORE_2_PSP_MSG_38_FUSE_SPL) {
151  printk(BIOS_DEBUG, "PSP: Fuse SPL requested\n");
153  psp_print_cmd_status(cmd_status, NULL);
154  } else {
155  printk(BIOS_DEBUG, "PSP: Fuse SPL not requested\n");
156  }
157 }
158 
static int wait_for_ready(u8 *base)
@ BS_PAYLOAD_BOOT
Definition: bootstate.h:89
@ BS_ON_ENTRY
Definition: bootstate.h:95
cb_err
coreboot error codes
Definition: cb_err.h:15
@ CB_ERR
Generic error code.
Definition: cb_err.h:17
@ CB_SUCCESS
Call completed successfully.
Definition: cb_err.h:16
void psp_print_cmd_status(int cmd_status, struct mbox_buffer_header *header)
Definition: psp.c:47
#define printk(level,...)
Definition: stdlib.h:16
@ CONFIG
Definition: dsi_common.h:201
#define PSP_ADDR_MSR
Definition: msr.h:81
static __always_inline msr_t rdmsr(unsigned int index)
Definition: msr.h:146
static __always_inline void write64p(const uintptr_t addr, const uint64_t value)
Definition: mmio.h:245
static __always_inline uint32_t read32p(const uintptr_t addr)
Definition: mmio.h:220
static __always_inline void write32p(const uintptr_t addr, const uint32_t value)
Definition: mmio.h:240
static int stopwatch_expired(struct stopwatch *sw)
Definition: timer.h:152
static void stopwatch_init_msecs_expire(struct stopwatch *sw, long ms)
Definition: timer.h:133
#define BIOS_DEBUG
BIOS_DEBUG - Verbose output.
Definition: loglevel.h:128
#define BIOS_ERR
BIOS_ERR - System in incomplete state.
Definition: loglevel.h:72
#define BIOS_WARNING
BIOS_WARNING - Bad configuration.
Definition: loglevel.h:86
#define PSPSTS_NOBASE
Definition: psp.h:43
#define PSPSTS_RECOVERY
Definition: psp.h:45
#define PSPSTS_CMD_TIMEOUT
Definition: psp.h:48
#define PSPSTS_SEND_ERROR
Definition: psp.h:46
#define CORE_2_PSP_MSG_38_FUSE_SPL
Definition: psp_def.h:30
#define CORE_2_PSP_MSG_38_OFFSET
Definition: psp_def.h:29
#define PSP_CMD_TIMEOUT
Definition: psp_def.h:85
#define MBOX_BIOS_CMD_SET_SPL_FUSE
Definition: psp_def.h:20
#define MBOX_BIOS_CMD_SX_INFO
Definition: psp_def.h:12
#define PSP_MAILBOX_COMMAND_OFFSET
Definition: psp_gen2.c:13
static int wait_command(uintptr_t psp_mmio, bool wait_for_ready)
Definition: psp_gen2.c:65
enum cb_err soc_read_c2p38(uint32_t *msg_38_value)
Definition: psp_gen2.c:120
static uintptr_t soc_get_psp_base_address(void)
Definition: psp_gen2.c:27
int send_psp_command(u32 command, void *buffer)
Definition: psp_gen2.c:92
static void wr_mbox_cmd(uintptr_t psp_mmio, u8 cmd)
Definition: psp_gen2.c:43
static u16 rd_mbox_sts(uintptr_t psp_mmio)
Definition: psp_gen2.c:35
static void wr_mbox_buffer_ptr(uintptr_t psp_mmio, void *buffer)
Definition: psp_gen2.c:60
#define PSP_MAILBOX_BUFFER_OFFSET
Definition: psp_gen2.c:14
BOOT_STATE_INIT_ENTRY(BS_PAYLOAD_BOOT, BS_ON_ENTRY, psp_set_spl_fuse, NULL)
static u8 rd_mbox_recovery(uintptr_t psp_mmio)
Definition: psp_gen2.c:52
static void psp_set_spl_fuse(void *unused)
Definition: psp_gen2.c:132
u8 buffer[C2P_BUFFER_MAXSIZE]
Definition: psp_smm.c:18
#define NULL
Definition: stddef.h:19
unsigned int uint32_t
Definition: stdint.h:14
uint32_t u32
Definition: stdint.h:51
unsigned long uintptr_t
Definition: stdint.h:21
uint16_t u16
Definition: stdint.h:48
uint8_t u8
Definition: stdint.h:45
Definition: x86.c:23
unsigned int lo
Definition: msr.h:111
struct pspv2_mbox_command::pspv2_mbox_cmd_fields fields