1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AMD Platform Security Processor (PSP) Platform Access interface 4 * 5 * Copyright (C) 2023 Advanced Micro Devices, Inc. 6 * 7 * Author: Mario Limonciello <mario.limonciello@amd.com> 8 * 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. 11 * 12 */ 13 14 #include <linux/bitfield.h> 15 #include <linux/errno.h> 16 #include <linux/iopoll.h> 17 #include <linux/mutex.h> 18 19 #include "platform-access.h" 20 21 #define PSP_CMD_TIMEOUT_US (500 * USEC_PER_MSEC) 22 23 /* Doorbell shouldn't be ringing */ 24 static int check_doorbell(u32 __iomem *doorbell) 25 { 26 u32 tmp; 27 28 return readl_poll_timeout(doorbell, tmp, tmp != 0, 0, PSP_CMD_TIMEOUT_US); 29 } 30 31 /* Recovery field should be equal 0 to start sending commands */ 32 static int check_recovery(u32 __iomem *cmd) 33 { 34 return FIELD_GET(PSP_CMDRESP_RECOVERY, ioread32(cmd)); 35 } 36 37 static int wait_cmd(u32 __iomem *cmd) 38 { 39 u32 tmp, expected; 40 41 /* Expect mbox_cmd to be cleared and ready bit to be set by PSP */ 42 expected = FIELD_PREP(PSP_CMDRESP_RESP, 1); 43 44 /* 45 * Check for readiness of PSP mailbox in a tight loop in order to 46 * process further as soon as command was consumed. 47 */ 48 return readl_poll_timeout(cmd, tmp, (tmp & expected), 0, 49 PSP_CMD_TIMEOUT_US); 50 } 51 52 int psp_check_platform_access_status(void) 53 { 54 struct psp_device *psp = psp_get_master_device(); 55 56 if (!psp || !psp->platform_access_data) 57 return -ENODEV; 58 59 return 0; 60 } 61 EXPORT_SYMBOL(psp_check_platform_access_status); 62 63 int psp_send_platform_access_msg(enum psp_platform_access_msg msg, 64 struct psp_request *req) 65 { 66 struct psp_device *psp = psp_get_master_device(); 67 u32 __iomem *cmd, *lo, *hi; 68 struct psp_platform_access_device *pa_dev; 69 phys_addr_t req_addr; 70 u32 cmd_reg; 71 int ret; 72 73 if (!psp || !psp->platform_access_data) 74 return -ENODEV; 75 76 pa_dev = psp->platform_access_data; 77 cmd = psp->io_regs + pa_dev->vdata->cmdresp_reg; 78 lo = psp->io_regs + pa_dev->vdata->cmdbuff_addr_lo_reg; 79 hi = psp->io_regs + pa_dev->vdata->cmdbuff_addr_hi_reg; 80 81 mutex_lock(&pa_dev->mailbox_mutex); 82 83 if (check_recovery(cmd)) { 84 dev_dbg(psp->dev, "platform mailbox is in recovery\n"); 85 ret = -EBUSY; 86 goto unlock; 87 } 88 89 if (wait_cmd(cmd)) { 90 dev_dbg(psp->dev, "platform mailbox is not done processing command\n"); 91 ret = -EBUSY; 92 goto unlock; 93 } 94 95 /* 96 * Fill mailbox with address of command-response buffer, which will be 97 * used for sending i2c requests as well as reading status returned by 98 * PSP. Use physical address of buffer, since PSP will map this region. 99 */ 100 req_addr = __psp_pa(req); 101 iowrite32(lower_32_bits(req_addr), lo); 102 iowrite32(upper_32_bits(req_addr), hi); 103 104 print_hex_dump_debug("->psp ", DUMP_PREFIX_OFFSET, 16, 2, req, 105 req->header.payload_size, false); 106 107 /* Write command register to trigger processing */ 108 cmd_reg = FIELD_PREP(PSP_CMDRESP_CMD, msg); 109 iowrite32(cmd_reg, cmd); 110 111 if (wait_cmd(cmd)) { 112 ret = -ETIMEDOUT; 113 goto unlock; 114 } 115 116 /* Ensure it was triggered by this driver */ 117 if (ioread32(lo) != lower_32_bits(req_addr) || 118 ioread32(hi) != upper_32_bits(req_addr)) { 119 ret = -EBUSY; 120 goto unlock; 121 } 122 123 /* Store the status in request header for caller to investigate */ 124 cmd_reg = ioread32(cmd); 125 req->header.status = FIELD_GET(PSP_CMDRESP_STS, cmd_reg); 126 if (req->header.status) { 127 ret = -EIO; 128 goto unlock; 129 } 130 131 print_hex_dump_debug("<-psp ", DUMP_PREFIX_OFFSET, 16, 2, req, 132 req->header.payload_size, false); 133 134 ret = 0; 135 136 unlock: 137 mutex_unlock(&pa_dev->mailbox_mutex); 138 139 return ret; 140 } 141 EXPORT_SYMBOL_GPL(psp_send_platform_access_msg); 142 143 int psp_ring_platform_doorbell(int msg) 144 { 145 struct psp_device *psp = psp_get_master_device(); 146 struct psp_platform_access_device *pa_dev; 147 u32 __iomem *button, *cmd; 148 int ret, val; 149 150 if (!psp || !psp->platform_access_data) 151 return -ENODEV; 152 153 pa_dev = psp->platform_access_data; 154 button = psp->io_regs + pa_dev->vdata->doorbell_button_reg; 155 cmd = psp->io_regs + pa_dev->vdata->doorbell_cmd_reg; 156 157 mutex_lock(&pa_dev->doorbell_mutex); 158 159 if (check_doorbell(button)) { 160 dev_dbg(psp->dev, "doorbell is not ready\n"); 161 ret = -EBUSY; 162 goto unlock; 163 } 164 165 if (check_recovery(cmd)) { 166 dev_dbg(psp->dev, "doorbell command in recovery\n"); 167 ret = -EBUSY; 168 goto unlock; 169 } 170 171 if (wait_cmd(cmd)) { 172 dev_dbg(psp->dev, "doorbell command not done processing\n"); 173 ret = -EBUSY; 174 goto unlock; 175 } 176 177 iowrite32(FIELD_PREP(PSP_DRBL_MSG, msg), cmd); 178 iowrite32(PSP_DRBL_RING, button); 179 180 if (wait_cmd(cmd)) { 181 ret = -ETIMEDOUT; 182 goto unlock; 183 } 184 185 val = FIELD_GET(PSP_CMDRESP_STS, ioread32(cmd)); 186 if (val) { 187 ret = -EIO; 188 goto unlock; 189 } 190 191 ret = 0; 192 unlock: 193 mutex_unlock(&pa_dev->doorbell_mutex); 194 195 return ret; 196 } 197 EXPORT_SYMBOL_GPL(psp_ring_platform_doorbell); 198 199 void platform_access_dev_destroy(struct psp_device *psp) 200 { 201 struct psp_platform_access_device *pa_dev = psp->platform_access_data; 202 203 if (!pa_dev) 204 return; 205 206 mutex_destroy(&pa_dev->mailbox_mutex); 207 mutex_destroy(&pa_dev->doorbell_mutex); 208 psp->platform_access_data = NULL; 209 } 210 211 int platform_access_dev_init(struct psp_device *psp) 212 { 213 struct device *dev = psp->dev; 214 struct psp_platform_access_device *pa_dev; 215 216 pa_dev = devm_kzalloc(dev, sizeof(*pa_dev), GFP_KERNEL); 217 if (!pa_dev) 218 return -ENOMEM; 219 220 psp->platform_access_data = pa_dev; 221 pa_dev->psp = psp; 222 pa_dev->dev = dev; 223 224 pa_dev->vdata = (struct platform_access_vdata *)psp->vdata->platform_access; 225 226 mutex_init(&pa_dev->mailbox_mutex); 227 mutex_init(&pa_dev->doorbell_mutex); 228 229 dev_dbg(dev, "platform access enabled\n"); 230 231 return 0; 232 } 233