Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 1 | /* SPDX-License-Identifier: GPL-2.0-only */ |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 2 | |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 3 | #include <timer.h> |
Martin Roth | bd6deb9 | 2023-03-06 17:47:54 -0700 | [diff] [blame] | 4 | #include <types.h> |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 5 | #include <amdblocks/psp.h> |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 6 | #include <amdblocks/smn.h> |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 7 | #include "psp_def.h" |
| 8 | |
Felix Held | cc07fa5 | 2022-04-29 19:22:33 +0200 | [diff] [blame] | 9 | #define PSP_MAILBOX_COMMAND_OFFSET 0x10570 /* 4 bytes */ |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 10 | #define PSP_MAILBOX_BUFFER_L_OFFSET 0x10574 /* 4 bytes */ |
| 11 | #define PSP_MAILBOX_BUFFER_H_OFFSET 0x10578 /* 4 bytes */ |
Felix Held | 99f800c | 2022-04-29 15:47:01 +0200 | [diff] [blame] | 12 | |
Felix Held | 63e7b70 | 2022-04-29 18:41:03 +0200 | [diff] [blame] | 13 | union pspv2_mbox_command { |
| 14 | u32 val; |
| 15 | struct pspv2_mbox_cmd_fields { |
| 16 | u16 mbox_status; |
| 17 | u8 mbox_command; |
| 18 | u32 reserved:6; |
| 19 | u32 recovery:1; |
| 20 | u32 ready:1; |
| 21 | } __packed fields; |
| 22 | }; |
| 23 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 24 | static u16 rd_mbox_sts(void) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 25 | { |
Felix Held | 1333bcf | 2022-04-29 21:02:52 +0200 | [diff] [blame] | 26 | union pspv2_mbox_command tmp; |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 27 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 28 | tmp.val = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET); |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 29 | return tmp.fields.mbox_status; |
| 30 | } |
| 31 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 32 | static void wr_mbox_cmd(u8 cmd) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 33 | { |
Felix Held | 4452400 | 2022-04-29 18:42:14 +0200 | [diff] [blame] | 34 | union pspv2_mbox_command tmp = { .val = 0 }; |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 35 | |
| 36 | /* Write entire 32-bit area to begin command execution */ |
| 37 | tmp.fields.mbox_command = cmd; |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 38 | smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET, tmp.val); |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 39 | } |
| 40 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 41 | static u8 rd_mbox_recovery(void) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 42 | { |
Felix Held | 1333bcf | 2022-04-29 21:02:52 +0200 | [diff] [blame] | 43 | union pspv2_mbox_command tmp; |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 44 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 45 | tmp.val = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET); |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 46 | return !!tmp.fields.recovery; |
| 47 | } |
| 48 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 49 | static void wr_mbox_buffer_ptr(void *buffer) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 50 | { |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 51 | const uint32_t buf_addr_h = (uint64_t)(uintptr_t)buffer >> 32; |
| 52 | const uint32_t buf_addr_l = (uint64_t)(uintptr_t)buffer & 0xffffffff; |
| 53 | smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_BUFFER_H_OFFSET, buf_addr_h); |
| 54 | smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_BUFFER_L_OFFSET, buf_addr_l); |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 55 | } |
| 56 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 57 | static int wait_command(bool wait_for_ready) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 58 | { |
Felix Held | 63e7b70 | 2022-04-29 18:41:03 +0200 | [diff] [blame] | 59 | union pspv2_mbox_command and_mask = { .val = ~0 }; |
| 60 | union pspv2_mbox_command expected = { .val = 0 }; |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 61 | struct stopwatch sw; |
| 62 | u32 tmp; |
| 63 | |
| 64 | /* Zero fields from and_mask that should be kept */ |
| 65 | and_mask.fields.mbox_command = 0; |
| 66 | and_mask.fields.ready = wait_for_ready ? 0 : 1; |
| 67 | |
| 68 | /* Expect mbox_cmd == 0 but ready depends */ |
| 69 | if (wait_for_ready) |
| 70 | expected.fields.ready = 1; |
| 71 | |
| 72 | stopwatch_init_msecs_expire(&sw, PSP_CMD_TIMEOUT); |
| 73 | |
| 74 | do { |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 75 | tmp = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET); |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 76 | tmp &= ~and_mask.val; |
| 77 | if (tmp == expected.val) |
| 78 | return 0; |
| 79 | } while (!stopwatch_expired(&sw)); |
| 80 | |
| 81 | return -PSPSTS_CMD_TIMEOUT; |
| 82 | } |
| 83 | |
| 84 | int send_psp_command(u32 command, void *buffer) |
| 85 | { |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 86 | if (rd_mbox_recovery()) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 87 | return -PSPSTS_RECOVERY; |
| 88 | |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 89 | if (wait_command(true)) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 90 | return -PSPSTS_CMD_TIMEOUT; |
| 91 | |
| 92 | /* set address of command-response buffer and write command register */ |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 93 | wr_mbox_buffer_ptr(buffer); |
| 94 | wr_mbox_cmd(command); |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 95 | |
| 96 | /* PSP clears command register when complete. All commands except |
| 97 | * SxInfo set the Ready bit. */ |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 98 | if (wait_command(command != MBOX_BIOS_CMD_SX_INFO)) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 99 | return -PSPSTS_CMD_TIMEOUT; |
| 100 | |
| 101 | /* check delivery status */ |
Felix Held | 198cc26 | 2022-04-29 19:25:19 +0200 | [diff] [blame] | 102 | if (rd_mbox_sts()) |
Marshall Dawson | d6b7236 | 2020-03-05 11:44:24 -0700 | [diff] [blame] | 103 | return -PSPSTS_SEND_ERROR; |
| 104 | |
| 105 | return 0; |
| 106 | } |
Jason Glenesk | fd539b4 | 2022-01-28 14:53:07 -0800 | [diff] [blame] | 107 | |
Felix Held | 00ec1b9 | 2022-05-05 15:19:03 +0200 | [diff] [blame] | 108 | uint32_t soc_read_c2p38(void) |
Jason Glenesk | fd539b4 | 2022-01-28 14:53:07 -0800 | [diff] [blame] | 109 | { |
Felix Held | 00ec1b9 | 2022-05-05 15:19:03 +0200 | [diff] [blame] | 110 | return smn_read32(SMN_PSP_PUBLIC_BASE + CORE_2_PSP_MSG_38_OFFSET); |
Jason Glenesk | fd539b4 | 2022-01-28 14:53:07 -0800 | [diff] [blame] | 111 | } |