Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 2 | |
| 3 | #include <device/mmio.h> |
| 4 | #include <cpu/x86/msr.h> |
| 5 | #include <cpu/amd/msr.h> |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 6 | #include <region_file.h> |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 7 | #include <console/console.h> |
| 8 | #include <amdblocks/psp.h> |
| 9 | #include <soc/iomap.h> |
Elyes HAOUAS | 722e610 | 2020-06-13 12:52:24 +0200 | [diff] [blame] | 10 | #include <string.h> |
| 11 | |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 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]; |
Elyes Haouas | 2dc5c6e | 2023-09-07 19:40:56 +0200 | [diff] [blame^] | 19 | } __aligned(32) c2p_buffer; |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 20 | |
| 21 | struct { |
| 22 | u8 buffer[P2C_BUFFER_MAXSIZE]; |
Elyes Haouas | 2dc5c6e | 2023-09-07 19:40:56 +0200 | [diff] [blame^] | 23 | } __aligned(32) p2c_buffer; |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 24 | |
| 25 | static uint32_t smm_flag; /* Non-zero for SMM, clear when not */ |
| 26 | |
| 27 | static void set_smm_flag(void) |
| 28 | { |
| 29 | smm_flag = 1; |
| 30 | } |
| 31 | |
| 32 | static void clear_smm_flag(void) |
| 33 | { |
| 34 | smm_flag = 0; |
| 35 | } |
| 36 | |
| 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); |
Felix Held | 65c4b86 | 2023-03-09 19:29:16 +0100 | [diff] [blame] | 54 | buffer.req.smm_base = msr.raw; |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 55 | msr = rdmsr(SMM_MASK_MSR); |
Felix Held | 357cc65 | 2020-07-09 00:04:22 +0200 | [diff] [blame] | 56 | msr.lo &= 0xffff0000; /* mask SMM_TSEG_VALID and reserved bits */ |
Felix Held | 65c4b86 | 2023-03-09 19:29:16 +0100 | [diff] [blame] | 57 | buffer.req.smm_mask = msr.raw; |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 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 */ |
Felix Held | 7d30418 | 2020-04-15 17:05:38 +0200 | [diff] [blame] | 71 | psp_print_cmd_status(cmd_status, &buffer.header); |
Marshall Dawson | e8ffa9f | 2020-03-16 19:20:20 -0600 | [diff] [blame] | 72 | |
| 73 | return cmd_status; |
| 74 | } |
Felix Held | 43126ed | 2020-04-01 22:06:39 +0200 | [diff] [blame] | 75 | |
| 76 | /* Notify PSP the system is going to a sleep state. */ |
| 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 */ |
Felix Held | 7d30418 | 2020-04-15 17:05:38 +0200 | [diff] [blame] | 101 | psp_print_cmd_status(cmd_status, &buffer->header); |
Felix Held | 43126ed | 2020-04-01 22:06:39 +0200 | [diff] [blame] | 102 | } |