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>
9 #include <region_file.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>
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
35 uint32_t mbox_command
;
37 uint64_t cmd_response
; /* definition conflicts w/BKDG but matches agesa */
40 static void *soc_get_mbox_address(void)
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",
51 /* Determine if Bar3Hide has been set, and if hidden get the base from
53 if (pci_read_config32(SOC_PSP_DEV
, PSP_BAR_ENABLES
) & BAR3HIDE
) {
54 psp_mmio
= rdmsr(PSP_ADDR_MSR
).lo
;
56 printk(BIOS_WARNING
, "PSP: BAR hidden, PSP_ADDR_MSR uninitialized\n");
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
)
91 stopwatch_init_msecs_expire(&sw
, PSP_INIT_TIMEOUT
);
94 if (rd_mbox_sts(mbox
) & PSPV1_STATUS_INITIALIZED
)
96 } while (!stopwatch_expired(&sw
));
98 return -PSPSTS_INIT_TIMEOUT
;
101 static int wait_command(struct pspv1_mbox
*mbox
)
105 stopwatch_init_msecs_expire(&sw
, PSP_CMD_TIMEOUT
);
108 if (!rd_mbox_cmd(mbox
))
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();
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
;
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
)
161 command
= MBOX_BIOS_CMD_SMU_FW
;
164 command
= MBOX_BIOS_CMD_SMU_FW2
;
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
);
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
);
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)
200 struct mbox_default_buffer buffer
= {
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
);