1 /* SPDX-License-Identifier: GPL-2.0-only */
2
3 #include <device/mmio.h>
4 #include <cpu/x86/msr.h>
5 #include <cpu/amd/msr.h>
6 #include <region_file.h>
7 #include <console/console.h>
8 #include <amdblocks/psp.h>
9 #include <soc/iomap.h>
10 #include <string.h>
11
12 #include "psp_def.h"
13
14 #define C2P_BUFFER_MAXSIZE 0xc00 /* Core-to-PSP buffer */
15 #define P2C_BUFFER_MAXSIZE 0xc00 /* PSP-to-core buffer */
16
17 struct {
18 u8 buffer[C2P_BUFFER_MAXSIZE];
19 } __aligned(32) c2p_buffer;
20
21 struct {
22 u8 buffer[P2C_BUFFER_MAXSIZE];
23 } __aligned(32) p2c_buffer;
24
25 static uint32_t smm_flag; /* Non-zero for SMM, clear when not */
26
set_smm_flag(void)27 static void set_smm_flag(void)
28 {
29 smm_flag = 1;
30 }
31
clear_smm_flag(void)32 static void clear_smm_flag(void)
33 {
34 smm_flag = 0;
35 }
36
psp_notify_smm(void)37 int psp_notify_smm(void)
38 {
39 msr_t msr;
40 int cmd_status;
41 struct mbox_cmd_smm_info_buffer buffer = {
42 .header = {
43 .size = sizeof(buffer)
44 },
45 .req = {
46 .psp_smm_data_region = (uintptr_t)p2c_buffer.buffer,
47 .psp_smm_data_length = sizeof(p2c_buffer),
48 .psp_mbox_smm_buffer_address = (uintptr_t)c2p_buffer.buffer,
49 .psp_mbox_smm_flag_address = (uintptr_t)&smm_flag,
50 }
51 };
52
53 msr = rdmsr(SMM_ADDR_MSR);
54 buffer.req.smm_base = msr.raw;
55 msr = rdmsr(SMM_MASK_MSR);
56 msr.lo &= 0xffff0000; /* mask SMM_TSEG_VALID and reserved bits */
57 buffer.req.smm_mask = msr.raw;
58
59 soc_fill_smm_trig_info(&buffer.req.smm_trig_info);
60 #if (CONFIG(SOC_AMD_COMMON_BLOCK_PSP_GEN2))
61 soc_fill_smm_reg_info(&buffer.req.smm_reg_info);
62 #endif
63
64 printk(BIOS_DEBUG, "PSP: Notify SMM info... ");
65
66 set_smm_flag();
67 cmd_status = send_psp_command(MBOX_BIOS_CMD_SMM_INFO, &buffer);
68 clear_smm_flag();
69
70 /* buffer's status shouldn't change but report it if it does */
71 psp_print_cmd_status(cmd_status, &buffer.header);
72
73 return cmd_status;
74 }
75
76 /* Notify PSP the system is going to a sleep state. */
psp_notify_sx_info(u8 sleep_type)77 void psp_notify_sx_info(u8 sleep_type)
78 {
79 int cmd_status;
80 struct mbox_cmd_sx_info_buffer *buffer;
81
82 /* PSP verifies that this buffer is at the address specified in psp_notify_smm() */
83 buffer = (struct mbox_cmd_sx_info_buffer *)c2p_buffer.buffer;
84 memset(buffer, 0, sizeof(*buffer));
85 buffer->header.size = sizeof(*buffer);
86
87 if (sleep_type > MBOX_BIOS_CMD_SX_INFO_SLEEP_TYPE_MAX) {
88 printk(BIOS_ERR, "PSP: BUG: invalid sleep type 0x%x requested\n", sleep_type);
89 return;
90 }
91
92 printk(BIOS_DEBUG, "PSP: Prepare to enter sleep state %d... ", sleep_type);
93
94 buffer->sleep_type = sleep_type;
95
96 set_smm_flag();
97 cmd_status = send_psp_command(MBOX_BIOS_CMD_SX_INFO, buffer);
98 clear_smm_flag();
99
100 /* buffer's status shouldn't change but report it if it does */
101 psp_print_cmd_status(cmd_status, &buffer->header);
102 }
103