blob: f647dcd2158d98dbe8945aa94b2219564fddf3ed [file] [log] [blame]
Marshall Dawsond6b72362020-03-05 11:44:24 -07001/* SPDX-License-Identifier: GPL-2.0-only */
Marshall Dawsond6b72362020-03-05 11:44:24 -07002
Marshall Dawsond6b72362020-03-05 11:44:24 -07003#include <timer.h>
Martin Rothbd6deb92023-03-06 17:47:54 -07004#include <types.h>
Marshall Dawsond6b72362020-03-05 11:44:24 -07005#include <amdblocks/psp.h>
Felix Held198cc262022-04-29 19:25:19 +02006#include <amdblocks/smn.h>
Marshall Dawsond6b72362020-03-05 11:44:24 -07007#include "psp_def.h"
8
Felix Heldcc07fa52022-04-29 19:22:33 +02009#define PSP_MAILBOX_COMMAND_OFFSET 0x10570 /* 4 bytes */
Felix Held198cc262022-04-29 19:25:19 +020010#define PSP_MAILBOX_BUFFER_L_OFFSET 0x10574 /* 4 bytes */
11#define PSP_MAILBOX_BUFFER_H_OFFSET 0x10578 /* 4 bytes */
Felix Held99f800c2022-04-29 15:47:01 +020012
Felix Held63e7b702022-04-29 18:41:03 +020013union 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 Held198cc262022-04-29 19:25:19 +020024static u16 rd_mbox_sts(void)
Marshall Dawsond6b72362020-03-05 11:44:24 -070025{
Felix Held1333bcf2022-04-29 21:02:52 +020026 union pspv2_mbox_command tmp;
Marshall Dawsond6b72362020-03-05 11:44:24 -070027
Felix Held198cc262022-04-29 19:25:19 +020028 tmp.val = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET);
Marshall Dawsond6b72362020-03-05 11:44:24 -070029 return tmp.fields.mbox_status;
30}
31
Felix Held198cc262022-04-29 19:25:19 +020032static void wr_mbox_cmd(u8 cmd)
Marshall Dawsond6b72362020-03-05 11:44:24 -070033{
Felix Held44524002022-04-29 18:42:14 +020034 union pspv2_mbox_command tmp = { .val = 0 };
Marshall Dawsond6b72362020-03-05 11:44:24 -070035
36 /* Write entire 32-bit area to begin command execution */
37 tmp.fields.mbox_command = cmd;
Felix Held198cc262022-04-29 19:25:19 +020038 smn_write32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET, tmp.val);
Marshall Dawsond6b72362020-03-05 11:44:24 -070039}
40
Felix Held198cc262022-04-29 19:25:19 +020041static u8 rd_mbox_recovery(void)
Marshall Dawsond6b72362020-03-05 11:44:24 -070042{
Felix Held1333bcf2022-04-29 21:02:52 +020043 union pspv2_mbox_command tmp;
Marshall Dawsond6b72362020-03-05 11:44:24 -070044
Felix Held198cc262022-04-29 19:25:19 +020045 tmp.val = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET);
Marshall Dawsond6b72362020-03-05 11:44:24 -070046 return !!tmp.fields.recovery;
47}
48
Felix Held198cc262022-04-29 19:25:19 +020049static void wr_mbox_buffer_ptr(void *buffer)
Marshall Dawsond6b72362020-03-05 11:44:24 -070050{
Felix Held198cc262022-04-29 19:25:19 +020051 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 Dawsond6b72362020-03-05 11:44:24 -070055}
56
Felix Held198cc262022-04-29 19:25:19 +020057static int wait_command(bool wait_for_ready)
Marshall Dawsond6b72362020-03-05 11:44:24 -070058{
Felix Held63e7b702022-04-29 18:41:03 +020059 union pspv2_mbox_command and_mask = { .val = ~0 };
60 union pspv2_mbox_command expected = { .val = 0 };
Marshall Dawsond6b72362020-03-05 11:44:24 -070061 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 Held198cc262022-04-29 19:25:19 +020075 tmp = smn_read32(SMN_PSP_PUBLIC_BASE + PSP_MAILBOX_COMMAND_OFFSET);
Marshall Dawsond6b72362020-03-05 11:44:24 -070076 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
84int send_psp_command(u32 command, void *buffer)
85{
Felix Held198cc262022-04-29 19:25:19 +020086 if (rd_mbox_recovery())
Marshall Dawsond6b72362020-03-05 11:44:24 -070087 return -PSPSTS_RECOVERY;
88
Felix Held198cc262022-04-29 19:25:19 +020089 if (wait_command(true))
Marshall Dawsond6b72362020-03-05 11:44:24 -070090 return -PSPSTS_CMD_TIMEOUT;
91
92 /* set address of command-response buffer and write command register */
Felix Held198cc262022-04-29 19:25:19 +020093 wr_mbox_buffer_ptr(buffer);
94 wr_mbox_cmd(command);
Marshall Dawsond6b72362020-03-05 11:44:24 -070095
96 /* PSP clears command register when complete. All commands except
97 * SxInfo set the Ready bit. */
Felix Held198cc262022-04-29 19:25:19 +020098 if (wait_command(command != MBOX_BIOS_CMD_SX_INFO))
Marshall Dawsond6b72362020-03-05 11:44:24 -070099 return -PSPSTS_CMD_TIMEOUT;
100
101 /* check delivery status */
Felix Held198cc262022-04-29 19:25:19 +0200102 if (rd_mbox_sts())
Marshall Dawsond6b72362020-03-05 11:44:24 -0700103 return -PSPSTS_SEND_ERROR;
104
105 return 0;
106}
Jason Gleneskfd539b42022-01-28 14:53:07 -0800107
Felix Held00ec1b92022-05-05 15:19:03 +0200108uint32_t soc_read_c2p38(void)
Jason Gleneskfd539b42022-01-28 14:53:07 -0800109{
Felix Held00ec1b92022-05-05 15:19:03 +0200110 return smn_read32(SMN_PSP_PUBLIC_BASE + CORE_2_PSP_MSG_38_OFFSET);
Jason Gleneskfd539b42022-01-28 14:53:07 -0800111}