amd_hsmp.c (10614B)
1// SPDX-License-Identifier: GPL-2.0 2/* 3 * AMD HSMP Platform Driver 4 * Copyright (c) 2022, AMD. 5 * All Rights Reserved. 6 * 7 * This file provides a device implementation for HSMP interface 8 */ 9 10#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12#include <asm/amd_hsmp.h> 13#include <asm/amd_nb.h> 14#include <linux/delay.h> 15#include <linux/io.h> 16#include <linux/miscdevice.h> 17#include <linux/module.h> 18#include <linux/pci.h> 19#include <linux/platform_device.h> 20#include <linux/semaphore.h> 21 22#define DRIVER_NAME "amd_hsmp" 23#define DRIVER_VERSION "1.0" 24 25/* HSMP Status / Error codes */ 26#define HSMP_STATUS_NOT_READY 0x00 27#define HSMP_STATUS_OK 0x01 28#define HSMP_ERR_INVALID_MSG 0xFE 29#define HSMP_ERR_INVALID_INPUT 0xFF 30 31/* Timeout in millsec */ 32#define HSMP_MSG_TIMEOUT 100 33#define HSMP_SHORT_SLEEP 1 34 35#define HSMP_WR true 36#define HSMP_RD false 37 38/* 39 * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox 40 * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg. 41 * Below are required SMN address for HSMP Mailbox register offsets in SMU address space 42 */ 43#define SMN_HSMP_MSG_ID 0x3B10534 44#define SMN_HSMP_MSG_RESP 0x3B10980 45#define SMN_HSMP_MSG_DATA 0x3B109E0 46 47#define HSMP_INDEX_REG 0xc4 48#define HSMP_DATA_REG 0xc8 49 50static struct semaphore *hsmp_sem; 51 52static struct miscdevice hsmp_device; 53 54static int amd_hsmp_rdwr(struct pci_dev *root, u32 address, 55 u32 *value, bool write) 56{ 57 int ret; 58 59 ret = pci_write_config_dword(root, HSMP_INDEX_REG, address); 60 if (ret) 61 return ret; 62 63 ret = (write ? pci_write_config_dword(root, HSMP_DATA_REG, *value) 64 : pci_read_config_dword(root, HSMP_DATA_REG, value)); 65 66 return ret; 67} 68 69/* 70 * Send a message to the HSMP port via PCI-e config space registers. 71 * 72 * The caller is expected to zero out any unused arguments. 73 * If a response is expected, the number of response words should be greater than 0. 74 * 75 * Returns 0 for success and populates the requested number of arguments. 76 * Returns a negative error code for failure. 77 */ 78static int __hsmp_send_message(struct pci_dev *root, struct hsmp_message *msg) 79{ 80 unsigned long timeout, short_sleep; 81 u32 mbox_status; 82 u32 index; 83 int ret; 84 85 /* Clear the status register */ 86 mbox_status = HSMP_STATUS_NOT_READY; 87 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_WR); 88 if (ret) { 89 pr_err("Error %d clearing mailbox status register\n", ret); 90 return ret; 91 } 92 93 index = 0; 94 /* Write any message arguments */ 95 while (index < msg->num_args) { 96 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_DATA + (index << 2), 97 &msg->args[index], HSMP_WR); 98 if (ret) { 99 pr_err("Error %d writing message argument %d\n", ret, index); 100 return ret; 101 } 102 index++; 103 } 104 105 /* Write the message ID which starts the operation */ 106 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_ID, &msg->msg_id, HSMP_WR); 107 if (ret) { 108 pr_err("Error %d writing message ID %u\n", ret, msg->msg_id); 109 return ret; 110 } 111 112 /* 113 * Depending on when the trigger write completes relative to the SMU 114 * firmware 1 ms cycle, the operation may take from tens of us to 1 ms 115 * to complete. Some operations may take more. Therefore we will try 116 * a few short duration sleeps and switch to long sleeps if we don't 117 * succeed quickly. 118 */ 119 short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP); 120 timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT); 121 122 while (time_before(jiffies, timeout)) { 123 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_RD); 124 if (ret) { 125 pr_err("Error %d reading mailbox status\n", ret); 126 return ret; 127 } 128 129 if (mbox_status != HSMP_STATUS_NOT_READY) 130 break; 131 if (time_before(jiffies, short_sleep)) 132 usleep_range(50, 100); 133 else 134 usleep_range(1000, 2000); 135 } 136 137 if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) { 138 return -ETIMEDOUT; 139 } else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) { 140 return -ENOMSG; 141 } else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) { 142 return -EINVAL; 143 } else if (unlikely(mbox_status != HSMP_STATUS_OK)) { 144 pr_err("Message ID %u unknown failure (status = 0x%X)\n", 145 msg->msg_id, mbox_status); 146 return -EIO; 147 } 148 149 /* 150 * SMU has responded OK. Read response data. 151 * SMU reads the input arguments from eight 32 bit registers starting 152 * from SMN_HSMP_MSG_DATA and writes the response data to the same 153 * SMN_HSMP_MSG_DATA address. 154 * We copy the response data if any, back to the args[]. 155 */ 156 index = 0; 157 while (index < msg->response_sz) { 158 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_DATA + (index << 2), 159 &msg->args[index], HSMP_RD); 160 if (ret) { 161 pr_err("Error %d reading response %u for message ID:%u\n", 162 ret, index, msg->msg_id); 163 break; 164 } 165 index++; 166 } 167 168 return ret; 169} 170 171static int validate_message(struct hsmp_message *msg) 172{ 173 /* msg_id against valid range of message IDs */ 174 if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX) 175 return -ENOMSG; 176 177 /* msg_id is a reserved message ID */ 178 if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD) 179 return -ENOMSG; 180 181 /* num_args and response_sz against the HSMP spec */ 182 if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args || 183 msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz) 184 return -EINVAL; 185 186 return 0; 187} 188 189int hsmp_send_message(struct hsmp_message *msg) 190{ 191 struct amd_northbridge *nb; 192 int ret; 193 194 if (!msg) 195 return -EINVAL; 196 197 nb = node_to_amd_nb(msg->sock_ind); 198 if (!nb || !nb->root) 199 return -ENODEV; 200 201 ret = validate_message(msg); 202 if (ret) 203 return ret; 204 205 /* 206 * The time taken by smu operation to complete is between 207 * 10us to 1ms. Sometime it may take more time. 208 * In SMP system timeout of 100 millisecs should 209 * be enough for the previous thread to finish the operation 210 */ 211 ret = down_timeout(&hsmp_sem[msg->sock_ind], 212 msecs_to_jiffies(HSMP_MSG_TIMEOUT)); 213 if (ret < 0) 214 return ret; 215 216 ret = __hsmp_send_message(nb->root, msg); 217 218 up(&hsmp_sem[msg->sock_ind]); 219 220 return ret; 221} 222EXPORT_SYMBOL_GPL(hsmp_send_message); 223 224static int hsmp_test(u16 sock_ind, u32 value) 225{ 226 struct hsmp_message msg = { 0 }; 227 struct amd_northbridge *nb; 228 int ret = -ENODEV; 229 230 nb = node_to_amd_nb(sock_ind); 231 if (!nb || !nb->root) 232 return ret; 233 234 /* 235 * Test the hsmp port by performing TEST command. The test message 236 * takes one argument and returns the value of that argument + 1. 237 */ 238 msg.msg_id = HSMP_TEST; 239 msg.num_args = 1; 240 msg.response_sz = 1; 241 msg.args[0] = value; 242 msg.sock_ind = sock_ind; 243 244 ret = __hsmp_send_message(nb->root, &msg); 245 if (ret) 246 return ret; 247 248 /* Check the response value */ 249 if (msg.args[0] != (value + 1)) { 250 pr_err("Socket %d test message failed, Expected 0x%08X, received 0x%08X\n", 251 sock_ind, (value + 1), msg.args[0]); 252 return -EBADE; 253 } 254 255 return ret; 256} 257 258static long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg) 259{ 260 int __user *arguser = (int __user *)arg; 261 struct hsmp_message msg = { 0 }; 262 int ret; 263 264 if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message))) 265 return -EFAULT; 266 267 /* 268 * Check msg_id is within the range of supported msg ids 269 * i.e within the array bounds of hsmp_msg_desc_table 270 */ 271 if (msg.msg_id < HSMP_TEST || msg.msg_id >= HSMP_MSG_ID_MAX) 272 return -ENOMSG; 273 274 switch (fp->f_mode & (FMODE_WRITE | FMODE_READ)) { 275 case FMODE_WRITE: 276 /* 277 * Device is opened in O_WRONLY mode 278 * Execute only set/configure commands 279 */ 280 if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET) 281 return -EINVAL; 282 break; 283 case FMODE_READ: 284 /* 285 * Device is opened in O_RDONLY mode 286 * Execute only get/monitor commands 287 */ 288 if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET) 289 return -EINVAL; 290 break; 291 case FMODE_READ | FMODE_WRITE: 292 /* 293 * Device is opened in O_RDWR mode 294 * Execute both get/monitor and set/configure commands 295 */ 296 break; 297 default: 298 return -EINVAL; 299 } 300 301 ret = hsmp_send_message(&msg); 302 if (ret) 303 return ret; 304 305 if (hsmp_msg_desc_table[msg.msg_id].response_sz > 0) { 306 /* Copy results back to user for get/monitor commands */ 307 if (copy_to_user(arguser, &msg, sizeof(struct hsmp_message))) 308 return -EFAULT; 309 } 310 311 return 0; 312} 313 314static const struct file_operations hsmp_fops = { 315 .owner = THIS_MODULE, 316 .unlocked_ioctl = hsmp_ioctl, 317 .compat_ioctl = hsmp_ioctl, 318}; 319 320static int hsmp_pltdrv_probe(struct platform_device *pdev) 321{ 322 int i; 323 324 hsmp_sem = devm_kzalloc(&pdev->dev, 325 (amd_nb_num() * sizeof(struct semaphore)), 326 GFP_KERNEL); 327 if (!hsmp_sem) 328 return -ENOMEM; 329 330 for (i = 0; i < amd_nb_num(); i++) 331 sema_init(&hsmp_sem[i], 1); 332 333 hsmp_device.name = "hsmp_cdev"; 334 hsmp_device.minor = MISC_DYNAMIC_MINOR; 335 hsmp_device.fops = &hsmp_fops; 336 hsmp_device.parent = &pdev->dev; 337 hsmp_device.nodename = "hsmp"; 338 hsmp_device.mode = 0644; 339 340 return misc_register(&hsmp_device); 341} 342 343static int hsmp_pltdrv_remove(struct platform_device *pdev) 344{ 345 misc_deregister(&hsmp_device); 346 347 return 0; 348} 349 350static struct platform_driver amd_hsmp_driver = { 351 .probe = hsmp_pltdrv_probe, 352 .remove = hsmp_pltdrv_remove, 353 .driver = { 354 .name = DRIVER_NAME, 355 }, 356}; 357 358static struct platform_device *amd_hsmp_platdev; 359 360static int __init hsmp_plt_init(void) 361{ 362 int ret = -ENODEV; 363 u16 num_sockets; 364 int i; 365 366 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD || boot_cpu_data.x86 < 0x19) { 367 pr_err("HSMP is not supported on Family:%x model:%x\n", 368 boot_cpu_data.x86, boot_cpu_data.x86_model); 369 return ret; 370 } 371 372 /* 373 * amd_nb_num() returns number of SMN/DF interfaces present in the system 374 * if we have N SMN/DF interfaces that ideally means N sockets 375 */ 376 num_sockets = amd_nb_num(); 377 if (num_sockets == 0) 378 return ret; 379 380 /* Test the hsmp interface on each socket */ 381 for (i = 0; i < num_sockets; i++) { 382 ret = hsmp_test(i, 0xDEADBEEF); 383 if (ret) { 384 pr_err("HSMP is not supported on Fam:%x model:%x\n", 385 boot_cpu_data.x86, boot_cpu_data.x86_model); 386 pr_err("Or Is HSMP disabled in BIOS ?\n"); 387 return -EOPNOTSUPP; 388 } 389 } 390 391 ret = platform_driver_register(&amd_hsmp_driver); 392 if (ret) 393 return ret; 394 395 amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, -1); 396 if (!amd_hsmp_platdev) { 397 ret = -ENOMEM; 398 goto drv_unregister; 399 } 400 401 ret = platform_device_add(amd_hsmp_platdev); 402 if (ret) { 403 platform_device_put(amd_hsmp_platdev); 404 goto drv_unregister; 405 } 406 407 return 0; 408 409drv_unregister: 410 platform_driver_unregister(&amd_hsmp_driver); 411 return ret; 412} 413 414static void __exit hsmp_plt_exit(void) 415{ 416 platform_device_unregister(amd_hsmp_platdev); 417 platform_driver_unregister(&amd_hsmp_driver); 418} 419 420device_initcall(hsmp_plt_init); 421module_exit(hsmp_plt_exit); 422 423MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 424MODULE_VERSION(DRIVER_VERSION); 425MODULE_LICENSE("GPL v2");