mb/google/nissa/var/rull: Configure Acoustic noise mitigation
[coreboot2.git] / src / soc / amd / common / block / psp / psp_gen1.c
blobb3815f9283d18e1999dc20b08792407e724d8c36
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <cpu/amd/msr.h>
4 #include <cpu/x86/msr.h>
5 #include <device/mmio.h>
6 #include <device/pci_ops.h>
7 #include <device/pci_def.h>
8 #include <cbfs.h>
9 #include <region_file.h>
10 #include <timer.h>
11 #include <console/console.h>
12 #include <amdblocks/psp.h>
13 #include <soc/iomap.h>
14 #include <soc/northbridge.h>
15 #include <soc/pci_devs.h>
16 #include <soc/southbridge.h>
17 #include "psp_def.h"
19 #define PSP_MAILBOX_OFFSET 0x70
21 /* generic PSP interface status, v1 */
22 #define PSPV1_STATUS_INITIALIZED BIT(0)
23 #define PSPV1_STATUS_ERROR BIT(1)
24 #define PSPV1_STATUS_TERMINATED BIT(2)
25 #define PSPV1_STATUS_HALT BIT(3)
26 #define PSPV1_STATUS_RECOVERY BIT(4)
29 * pspv1_mbox consists of hardware registers beginning at PSPx000070
30 * mbox_command: BIOS->PSP command, cleared by PSP when complete
31 * mbox_status: BIOS->PSP interface status
32 * cmd_response: pointer to command/response buffer
34 struct pspv1_mbox {
35 uint32_t mbox_command;
36 uint32_t mbox_status;
37 uint64_t cmd_response; /* definition conflicts w/BKDG but matches agesa */
38 } __packed;
40 static void *soc_get_mbox_address(void)
42 uintptr_t psp_mmio;
44 /* Check for presence of the PSP */
45 if (pci_read_config32(SOC_PSP_DEV, PCI_VENDOR_ID) == 0xffffffff) {
46 printk(BIOS_WARNING, "PSP: No SOC_PSP_DEV found at D%xF%x\n",
47 PSP_DEV, PSP_FUNC);
48 return 0;
51 /* Determine if Bar3Hide has been set, and if hidden get the base from
52 * the MSR instead. */
53 if (pci_read_config32(SOC_PSP_DEV, PSP_BAR_ENABLES) & BAR3HIDE) {
54 psp_mmio = rdmsr(PSP_ADDR_MSR).lo;
55 if (!psp_mmio) {
56 printk(BIOS_WARNING, "PSP: BAR hidden, PSP_ADDR_MSR uninitialized\n");
57 return 0;
59 } else {
60 psp_mmio = pci_read_config32(SOC_PSP_DEV, PSP_MAILBOX_BAR) &
61 ~PCI_BASE_ADDRESS_MEM_ATTR_MASK;
64 return (void *)(psp_mmio + PSP_MAILBOX_OFFSET);
67 static uint32_t rd_mbox_sts(struct pspv1_mbox *mbox)
69 return read32(&mbox->mbox_status);
72 static void wr_mbox_cmd(struct pspv1_mbox *mbox, uint32_t cmd)
74 write32(&mbox->mbox_command, cmd);
77 static uint32_t rd_mbox_cmd(struct pspv1_mbox *mbox)
79 return read32(&mbox->mbox_command);
82 static void wr_mbox_cmd_resp(struct pspv1_mbox *mbox, void *buffer)
84 write64(&mbox->cmd_response, (uintptr_t)buffer);
87 static int wait_initialized(struct pspv1_mbox *mbox)
89 struct stopwatch sw;
91 stopwatch_init_msecs_expire(&sw, PSP_INIT_TIMEOUT);
93 do {
94 if (rd_mbox_sts(mbox) & PSPV1_STATUS_INITIALIZED)
95 return 0;
96 } while (!stopwatch_expired(&sw));
98 return -PSPSTS_INIT_TIMEOUT;
101 static int wait_command(struct pspv1_mbox *mbox)
103 struct stopwatch sw;
105 stopwatch_init_msecs_expire(&sw, PSP_CMD_TIMEOUT);
107 do {
108 if (!rd_mbox_cmd(mbox))
109 return 0;
110 } while (!stopwatch_expired(&sw));
112 return -PSPSTS_CMD_TIMEOUT;
115 int send_psp_command(uint32_t command, void *buffer)
117 struct pspv1_mbox *mbox = soc_get_mbox_address();
118 if (!mbox)
119 return -PSPSTS_NOBASE;
121 /* check for PSP error conditions */
122 if (rd_mbox_sts(mbox) & PSPV1_STATUS_HALT)
123 return -PSPSTS_HALTED;
125 if (rd_mbox_sts(mbox) & PSPV1_STATUS_RECOVERY)
126 return -PSPSTS_RECOVERY;
128 /* PSP must be finished with init and ready to accept a command */
129 if (wait_initialized(mbox))
130 return -PSPSTS_INIT_TIMEOUT;
132 if (wait_command(mbox))
133 return -PSPSTS_CMD_TIMEOUT;
135 /* set address of command-response buffer and write command register */
136 wr_mbox_cmd_resp(mbox, buffer);
137 wr_mbox_cmd(mbox, command);
139 /* PSP clears command register when complete */
140 if (wait_command(mbox))
141 return -PSPSTS_CMD_TIMEOUT;
143 /* check delivery status */
144 if (rd_mbox_sts(mbox) & (PSPV1_STATUS_ERROR | PSPV1_STATUS_TERMINATED))
145 return -PSPSTS_SEND_ERROR;
147 return 0;
151 * Tell the PSP to load a firmware blob from a location in the BIOS image.
153 int psp_load_named_blob(enum psp_blob_type type, const char *name)
155 int cmd_status;
156 uint32_t command;
157 void *blob;
159 switch (type) {
160 case BLOB_SMU_FW:
161 command = MBOX_BIOS_CMD_SMU_FW;
162 break;
163 case BLOB_SMU_FW2:
164 command = MBOX_BIOS_CMD_SMU_FW2;
165 break;
166 default:
167 printk(BIOS_ERR, "BUG: Invalid PSP blob type %x\n", type);
168 return -PSPSTS_INVALID_BLOB;
171 /* type can only be BLOB_SMU_FW or BLOB_SMU_FW2 here, so don't re-check for this */
172 if (!CONFIG(SOC_AMD_PSP_SELECTABLE_SMU_FW)) {
173 printk(BIOS_ERR, "BUG: Selectable firmware is not supported\n");
174 return -PSPSTS_UNSUPPORTED;
177 blob = cbfs_map(name, NULL);
178 if (!blob) {
179 printk(BIOS_ERR, "BUG: Cannot map blob for PSP loading\n");
180 return -PSPSTS_INVALID_NAME;
183 printk(BIOS_DEBUG, "PSP: Load blob type %x from @%p... ", type, blob);
185 /* Blob commands use the buffer registers as data, not pointer to buf */
186 cmd_status = send_psp_command(command, blob);
187 psp_print_cmd_status(cmd_status, NULL);
189 cbfs_unmap(blob);
190 return cmd_status;
194 * Notify the PSP that DRAM is present. Upon receiving this command, the PSP
195 * will load its OS into fenced DRAM that is not accessible to the x86 cores.
197 int psp_notify_dram(void)
199 int cmd_status;
200 struct mbox_default_buffer buffer = {
201 .header = {
202 .size = sizeof(buffer)
206 printk(BIOS_DEBUG, "PSP: Notify that DRAM is available... ");
208 cmd_status = send_psp_command(MBOX_BIOS_CMD_DRAM_INFO, &buffer);
210 /* buffer's status shouldn't change but report it if it does */
211 psp_print_cmd_status(cmd_status, &buffer.header);
213 return cmd_status;