1 // SPDX-License-Identifier: GPL-2.0
3 * AMD Platform Security Processor (PSP) Platform Access interface
5 * Copyright (C) 2023 Advanced Micro Devices, Inc.
7 * Author: Mario Limonciello <mario.limonciello@amd.com>
9 * Some of this code is adapted from drivers/i2c/busses/i2c-designware-amdpsp.c
10 * developed by Jan Dabros <jsd@semihalf.com> and Copyright (C) 2022 Google Inc.
14 #include <linux/bitfield.h>
15 #include <linux/errno.h>
16 #include <linux/iopoll.h>
17 #include <linux/mutex.h>
19 #include "platform-access.h"
21 #define PSP_CMD_TIMEOUT_US (500 * USEC_PER_MSEC)
22 #define DOORBELL_CMDRESP_STS GENMASK(7, 0)
24 /* Recovery field should be equal 0 to start sending commands */
25 static int check_recovery(u32 __iomem
*cmd
)
27 return FIELD_GET(PSP_CMDRESP_RECOVERY
, ioread32(cmd
));
30 static int wait_cmd(u32 __iomem
*cmd
)
34 /* Expect mbox_cmd to be cleared and ready bit to be set by PSP */
35 expected
= FIELD_PREP(PSP_CMDRESP_RESP
, 1);
38 * Check for readiness of PSP mailbox in a tight loop in order to
39 * process further as soon as command was consumed.
41 return readl_poll_timeout(cmd
, tmp
, (tmp
& expected
), 0,
45 int psp_check_platform_access_status(void)
47 struct psp_device
*psp
= psp_get_master_device();
49 if (!psp
|| !psp
->platform_access_data
)
54 EXPORT_SYMBOL(psp_check_platform_access_status
);
56 int psp_send_platform_access_msg(enum psp_platform_access_msg msg
,
57 struct psp_request
*req
)
59 struct psp_device
*psp
= psp_get_master_device();
60 u32 __iomem
*cmd
, *lo
, *hi
;
61 struct psp_platform_access_device
*pa_dev
;
66 if (!psp
|| !psp
->platform_access_data
)
69 pa_dev
= psp
->platform_access_data
;
71 if (!pa_dev
->vdata
->cmdresp_reg
|| !pa_dev
->vdata
->cmdbuff_addr_lo_reg
||
72 !pa_dev
->vdata
->cmdbuff_addr_hi_reg
)
75 cmd
= psp
->io_regs
+ pa_dev
->vdata
->cmdresp_reg
;
76 lo
= psp
->io_regs
+ pa_dev
->vdata
->cmdbuff_addr_lo_reg
;
77 hi
= psp
->io_regs
+ pa_dev
->vdata
->cmdbuff_addr_hi_reg
;
79 mutex_lock(&pa_dev
->mailbox_mutex
);
81 if (check_recovery(cmd
)) {
82 dev_dbg(psp
->dev
, "platform mailbox is in recovery\n");
88 dev_dbg(psp
->dev
, "platform mailbox is not done processing command\n");
94 * Fill mailbox with address of command-response buffer, which will be
95 * used for sending i2c requests as well as reading status returned by
96 * PSP. Use physical address of buffer, since PSP will map this region.
98 req_addr
= __psp_pa(req
);
99 iowrite32(lower_32_bits(req_addr
), lo
);
100 iowrite32(upper_32_bits(req_addr
), hi
);
102 print_hex_dump_debug("->psp ", DUMP_PREFIX_OFFSET
, 16, 2, req
,
103 req
->header
.payload_size
, false);
105 /* Write command register to trigger processing */
106 cmd_reg
= FIELD_PREP(PSP_CMDRESP_CMD
, msg
);
107 iowrite32(cmd_reg
, cmd
);
114 /* Ensure it was triggered by this driver */
115 if (ioread32(lo
) != lower_32_bits(req_addr
) ||
116 ioread32(hi
) != upper_32_bits(req_addr
)) {
122 * Read status from PSP. If status is non-zero, it indicates an error
123 * occurred during "processing" of the command.
124 * If status is zero, it indicates the command was "processed"
125 * successfully, but the result of the command is in the payload.
126 * Return both cases to the caller as -EIO to investigate.
128 cmd_reg
= ioread32(cmd
);
129 if (FIELD_GET(PSP_CMDRESP_STS
, cmd_reg
))
130 req
->header
.status
= FIELD_GET(PSP_CMDRESP_STS
, cmd_reg
);
131 if (req
->header
.status
) {
136 print_hex_dump_debug("<-psp ", DUMP_PREFIX_OFFSET
, 16, 2, req
,
137 req
->header
.payload_size
, false);
142 mutex_unlock(&pa_dev
->mailbox_mutex
);
146 EXPORT_SYMBOL_GPL(psp_send_platform_access_msg
);
148 int psp_ring_platform_doorbell(int msg
, u32
*result
)
150 struct psp_device
*psp
= psp_get_master_device();
151 struct psp_platform_access_device
*pa_dev
;
152 u32 __iomem
*button
, *cmd
;
155 if (!psp
|| !psp
->platform_access_data
)
158 pa_dev
= psp
->platform_access_data
;
159 button
= psp
->io_regs
+ pa_dev
->vdata
->doorbell_button_reg
;
160 cmd
= psp
->io_regs
+ pa_dev
->vdata
->doorbell_cmd_reg
;
162 mutex_lock(&pa_dev
->doorbell_mutex
);
165 dev_err(psp
->dev
, "doorbell command not done processing\n");
170 iowrite32(FIELD_PREP(DOORBELL_CMDRESP_STS
, msg
), cmd
);
171 iowrite32(PSP_DRBL_RING
, button
);
178 val
= FIELD_GET(DOORBELL_CMDRESP_STS
, ioread32(cmd
));
188 mutex_unlock(&pa_dev
->doorbell_mutex
);
192 EXPORT_SYMBOL_GPL(psp_ring_platform_doorbell
);
194 void platform_access_dev_destroy(struct psp_device
*psp
)
196 struct psp_platform_access_device
*pa_dev
= psp
->platform_access_data
;
201 mutex_destroy(&pa_dev
->mailbox_mutex
);
202 mutex_destroy(&pa_dev
->doorbell_mutex
);
203 psp
->platform_access_data
= NULL
;
206 int platform_access_dev_init(struct psp_device
*psp
)
208 struct device
*dev
= psp
->dev
;
209 struct psp_platform_access_device
*pa_dev
;
211 pa_dev
= devm_kzalloc(dev
, sizeof(*pa_dev
), GFP_KERNEL
);
215 psp
->platform_access_data
= pa_dev
;
219 pa_dev
->vdata
= (struct platform_access_vdata
*)psp
->vdata
->platform_access
;
221 mutex_init(&pa_dev
->mailbox_mutex
);
222 mutex_init(&pa_dev
->doorbell_mutex
);
224 dev_dbg(dev
, "platform access enabled\n");