mb/google/nissa/var/rull: Configure Acoustic noise mitigation
[coreboot2.git] / src / soc / amd / common / block / psp / psp_gen2.c
blob21c1f2a7353fdf86bf372449a61b1a255d9e0974
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <timer.h>
4 #include <types.h>
5 #include <amdblocks/psp.h>
6 #include <amdblocks/root_complex.h>
7 #include <amdblocks/smn.h>
8 #include <device/mmio.h>
9 #include "psp_def.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;
19 size_t reg_count;
20 mmio_regs = get_iohc_non_pci_mmio_regs(&reg_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");
28 return 0;
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;
39 size_t iohc_count;
41 if (psp_mmio_base)
42 return psp_mmio_base;
44 iohc = get_iohc_info(&iohc_count);
45 const uint64_t psp_mmio_mask = get_psp_mmio_mask();
47 if (!psp_mmio_mask)
48 return 0;
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))
54 continue;
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");
60 continue;
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. "
67 "Locking it.\n", i);
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,
72 reg64 & 0xffffffff);
75 psp_mmio_base = base;
78 if (!psp_mmio_base)
79 printk(BIOS_ERR, "No usable PSP MMIO found.\n");
81 return psp_mmio_base;
84 union pspv2_mbox_command {
85 uint32_t val;
86 struct pspv2_mbox_cmd_fields {
87 uint16_t mbox_status;
88 uint8_t mbox_command;
89 uint32_t reserved:6;
90 uint32_t recovery:1;
91 uint32_t ready:1;
92 } __packed 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 };
129 struct stopwatch sw;
130 uint32_t tmp;
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 */
137 if (wait_for_ready)
138 expected.fields.ready = 1;
140 stopwatch_init_msecs_expire(&sw, PSP_CMD_TIMEOUT);
142 do {
143 tmp = read32p(psp_mmio | PSP_MAILBOX_COMMAND_OFFSET);
144 tmp &= ~and_mask.val;
145 if (tmp == expected.val)
146 return 0;
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();
155 if (!psp_mmio)
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;
177 return 0;
180 enum cb_err psp_get_psp_capabilities(uint32_t *capabilities)
182 int cmd_status;
183 struct mbox_cmd_capability_query_buffer buffer = {
184 .header = {
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);
196 if (cmd_status)
197 return CB_ERR;
199 *capabilities = read32(&buffer.capabilities);
200 return CB_SUCCESS;
203 enum cb_err soc_read_c2p38(uint32_t *msg_38_value)
205 const uintptr_t psp_mmio = get_psp_mmio_base();
207 if (!psp_mmio) {
208 printk(BIOS_WARNING, "PSP: PSP_ADDR_MSR uninitialized\n");
209 return CB_ERR;
211 *msg_38_value = read32p(psp_mmio | CORE_2_PSP_MSG_38_OFFSET);
212 return CB_SUCCESS;