1 /* SPDX-License-Identifier: GPL-2.0-only */
5 #include <amdblocks/psp.h>
6 #include <amdblocks/root_complex.h>
7 #include <amdblocks/smn.h>
8 #include <device/mmio.h>
11 #define PSP_MAILBOX_COMMAND_OFFSET 0x10570 /* 4 bytes */
12 #define PSP_MAILBOX_BUFFER_OFFSET 0x10574 /* 8 bytes */
14 #define IOHC_MISC_PSP_MMIO_REG 0x2e0
16 static uint64_t get_psp_mmio_mask(void)
18 const struct non_pci_mmio_reg
*mmio_regs
;
20 mmio_regs
= get_iohc_non_pci_mmio_regs(®_count
);
22 for (size_t i
= 0; i
< reg_count
; i
++) {
23 if (mmio_regs
[i
].iohc_misc_offset
== IOHC_MISC_PSP_MMIO_REG
)
24 return mmio_regs
[i
].mask
;
27 printk(BIOS_ERR
, "No PSP MMIO register description found.\n");
31 #define PSP_MMIO_LOCK BIT(8)
33 /* Getting the PSP MMIO base from the domain resources only works in ramstage, but not in SMM,
34 so we have to read this from the hardware registers */
35 uintptr_t get_psp_mmio_base(void)
37 static uintptr_t psp_mmio_base
;
38 const struct domain_iohc_info
*iohc
;
44 iohc
= get_iohc_info(&iohc_count
);
45 const uint64_t psp_mmio_mask
= get_psp_mmio_mask();
50 for (size_t i
= 0; i
< iohc_count
; i
++) {
51 uint64_t reg64
= smn_read64(iohc
[i
].misc_smn_base
| IOHC_MISC_PSP_MMIO_REG
);
53 if (!(reg64
& IOHC_MMIO_EN
))
56 const uint64_t base
= reg64
& psp_mmio_mask
;
58 if (ENV_X86_32
&& base
>= 4ull * GiB
) {
59 printk(BIOS_WARNING
, "PSP MMIO base above 4GB.\n");
63 /* If the PSP MMIO base is enabled but the register isn't locked, set the lock
64 bit. This shouldn't happen, but better be a bit too careful here */
65 if (!(reg64
& PSP_MMIO_LOCK
)) {
66 printk(BIOS_WARNING
, "Enabled PSP MMIO in domain %zu isn't locked. "
68 reg64
|= PSP_MMIO_LOCK
;
69 /* Since the lock bit lives in the lower one of the two 32 bit SMN
70 registers, we only need to write that one to lock it */
71 smn_write32(iohc
[i
].misc_smn_base
| IOHC_MISC_PSP_MMIO_REG
,
79 printk(BIOS_ERR
, "No usable PSP MMIO found.\n");
84 union pspv2_mbox_command
{
86 struct pspv2_mbox_cmd_fields
{
95 static uint16_t rd_mbox_sts(uintptr_t psp_mmio
)
97 union pspv2_mbox_command tmp
;
99 tmp
.val
= read32p(psp_mmio
| PSP_MAILBOX_COMMAND_OFFSET
);
100 return tmp
.fields
.mbox_status
;
103 static void wr_mbox_cmd(uintptr_t psp_mmio
, uint8_t cmd
)
105 union pspv2_mbox_command tmp
= { .val
= 0 };
107 /* Write entire 32-bit area to begin command execution */
108 tmp
.fields
.mbox_command
= cmd
;
109 write32p(psp_mmio
| PSP_MAILBOX_COMMAND_OFFSET
, tmp
.val
);
112 static uint8_t rd_mbox_recovery(uintptr_t psp_mmio
)
114 union pspv2_mbox_command tmp
;
116 tmp
.val
= read32p(psp_mmio
| PSP_MAILBOX_COMMAND_OFFSET
);
117 return !!tmp
.fields
.recovery
;
120 static void wr_mbox_buffer_ptr(uintptr_t psp_mmio
, void *buffer
)
122 write64p(psp_mmio
| PSP_MAILBOX_BUFFER_OFFSET
, (uintptr_t)buffer
);
125 static int wait_command(uintptr_t psp_mmio
, bool wait_for_ready
)
127 union pspv2_mbox_command and_mask
= { .val
= ~0 };
128 union pspv2_mbox_command expected
= { .val
= 0 };
132 /* Zero fields from and_mask that should be kept */
133 and_mask
.fields
.mbox_command
= 0;
134 and_mask
.fields
.ready
= wait_for_ready
? 0 : 1;
136 /* Expect mbox_cmd == 0 but ready depends */
138 expected
.fields
.ready
= 1;
140 stopwatch_init_msecs_expire(&sw
, PSP_CMD_TIMEOUT
);
143 tmp
= read32p(psp_mmio
| PSP_MAILBOX_COMMAND_OFFSET
);
144 tmp
&= ~and_mask
.val
;
145 if (tmp
== expected
.val
)
147 } while (!stopwatch_expired(&sw
));
149 return -PSPSTS_CMD_TIMEOUT
;
152 int send_psp_command(uint32_t command
, void *buffer
)
154 const uintptr_t psp_mmio
= get_psp_mmio_base();
156 return -PSPSTS_NOBASE
;
158 if (rd_mbox_recovery(psp_mmio
))
159 return -PSPSTS_RECOVERY
;
161 if (wait_command(psp_mmio
, true))
162 return -PSPSTS_CMD_TIMEOUT
;
164 /* set address of command-response buffer and write command register */
165 wr_mbox_buffer_ptr(psp_mmio
, buffer
);
166 wr_mbox_cmd(psp_mmio
, command
);
168 /* PSP clears command register when complete. All commands except
169 * SxInfo set the Ready bit. */
170 if (wait_command(psp_mmio
, command
!= MBOX_BIOS_CMD_SX_INFO
))
171 return -PSPSTS_CMD_TIMEOUT
;
173 /* check delivery status */
174 if (rd_mbox_sts(psp_mmio
))
175 return -PSPSTS_SEND_ERROR
;
180 enum cb_err
psp_get_psp_capabilities(uint32_t *capabilities
)
183 struct mbox_cmd_capability_query_buffer buffer
= {
185 .size
= sizeof(buffer
)
189 printk(BIOS_DEBUG
, "PSP: Querying PSP capabilities...");
191 cmd_status
= send_psp_command(MBOX_BIOS_CMD_PSP_CAPS_QUERY
, &buffer
);
193 /* buffer's status shouldn't change but report it if it does */
194 psp_print_cmd_status(cmd_status
, &buffer
.header
);
199 *capabilities
= read32(&buffer
.capabilities
);
203 enum cb_err
soc_read_c2p38(uint32_t *msg_38_value
)
205 const uintptr_t psp_mmio
= get_psp_mmio_base();
208 printk(BIOS_WARNING
, "PSP: PSP_ADDR_MSR uninitialized\n");
211 *msg_38_value
= read32p(psp_mmio
| CORE_2_PSP_MSG_38_OFFSET
);