Loading...
Note: File does not exist in v4.6.
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 "2.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
50#define HSMP_CDEV_NAME "hsmp_cdev"
51#define HSMP_DEVNODE_NAME "hsmp"
52#define HSMP_METRICS_TABLE_NAME "metrics_bin"
53
54#define HSMP_ATTR_GRP_NAME_SIZE 10
55
56struct hsmp_socket {
57 struct bin_attribute hsmp_attr;
58 void __iomem *metric_tbl_addr;
59 struct semaphore hsmp_sem;
60 char name[HSMP_ATTR_GRP_NAME_SIZE];
61 u16 sock_ind;
62};
63
64struct hsmp_plat_device {
65 struct miscdevice hsmp_device;
66 struct hsmp_socket *sock;
67 struct device *dev;
68 u32 proto_ver;
69 u16 num_sockets;
70};
71
72static struct hsmp_plat_device plat_dev;
73
74static int amd_hsmp_rdwr(struct pci_dev *root, u32 address,
75 u32 *value, bool write)
76{
77 int ret;
78
79 ret = pci_write_config_dword(root, HSMP_INDEX_REG, address);
80 if (ret)
81 return ret;
82
83 ret = (write ? pci_write_config_dword(root, HSMP_DATA_REG, *value)
84 : pci_read_config_dword(root, HSMP_DATA_REG, value));
85
86 return ret;
87}
88
89/*
90 * Send a message to the HSMP port via PCI-e config space registers.
91 *
92 * The caller is expected to zero out any unused arguments.
93 * If a response is expected, the number of response words should be greater than 0.
94 *
95 * Returns 0 for success and populates the requested number of arguments.
96 * Returns a negative error code for failure.
97 */
98static int __hsmp_send_message(struct pci_dev *root, struct hsmp_message *msg)
99{
100 unsigned long timeout, short_sleep;
101 u32 mbox_status;
102 u32 index;
103 int ret;
104
105 /* Clear the status register */
106 mbox_status = HSMP_STATUS_NOT_READY;
107 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_WR);
108 if (ret) {
109 pr_err("Error %d clearing mailbox status register\n", ret);
110 return ret;
111 }
112
113 index = 0;
114 /* Write any message arguments */
115 while (index < msg->num_args) {
116 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_DATA + (index << 2),
117 &msg->args[index], HSMP_WR);
118 if (ret) {
119 pr_err("Error %d writing message argument %d\n", ret, index);
120 return ret;
121 }
122 index++;
123 }
124
125 /* Write the message ID which starts the operation */
126 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_ID, &msg->msg_id, HSMP_WR);
127 if (ret) {
128 pr_err("Error %d writing message ID %u\n", ret, msg->msg_id);
129 return ret;
130 }
131
132 /*
133 * Depending on when the trigger write completes relative to the SMU
134 * firmware 1 ms cycle, the operation may take from tens of us to 1 ms
135 * to complete. Some operations may take more. Therefore we will try
136 * a few short duration sleeps and switch to long sleeps if we don't
137 * succeed quickly.
138 */
139 short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP);
140 timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT);
141
142 while (time_before(jiffies, timeout)) {
143 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_RD);
144 if (ret) {
145 pr_err("Error %d reading mailbox status\n", ret);
146 return ret;
147 }
148
149 if (mbox_status != HSMP_STATUS_NOT_READY)
150 break;
151 if (time_before(jiffies, short_sleep))
152 usleep_range(50, 100);
153 else
154 usleep_range(1000, 2000);
155 }
156
157 if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) {
158 return -ETIMEDOUT;
159 } else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) {
160 return -ENOMSG;
161 } else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) {
162 return -EINVAL;
163 } else if (unlikely(mbox_status != HSMP_STATUS_OK)) {
164 pr_err("Message ID %u unknown failure (status = 0x%X)\n",
165 msg->msg_id, mbox_status);
166 return -EIO;
167 }
168
169 /*
170 * SMU has responded OK. Read response data.
171 * SMU reads the input arguments from eight 32 bit registers starting
172 * from SMN_HSMP_MSG_DATA and writes the response data to the same
173 * SMN_HSMP_MSG_DATA address.
174 * We copy the response data if any, back to the args[].
175 */
176 index = 0;
177 while (index < msg->response_sz) {
178 ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_DATA + (index << 2),
179 &msg->args[index], HSMP_RD);
180 if (ret) {
181 pr_err("Error %d reading response %u for message ID:%u\n",
182 ret, index, msg->msg_id);
183 break;
184 }
185 index++;
186 }
187
188 return ret;
189}
190
191static int validate_message(struct hsmp_message *msg)
192{
193 /* msg_id against valid range of message IDs */
194 if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX)
195 return -ENOMSG;
196
197 /* msg_id is a reserved message ID */
198 if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD)
199 return -ENOMSG;
200
201 /* num_args and response_sz against the HSMP spec */
202 if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args ||
203 msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz)
204 return -EINVAL;
205
206 return 0;
207}
208
209int hsmp_send_message(struct hsmp_message *msg)
210{
211 struct hsmp_socket *sock = &plat_dev.sock[msg->sock_ind];
212 struct amd_northbridge *nb;
213 int ret;
214
215 if (!msg)
216 return -EINVAL;
217
218 nb = node_to_amd_nb(msg->sock_ind);
219 if (!nb || !nb->root)
220 return -ENODEV;
221
222 ret = validate_message(msg);
223 if (ret)
224 return ret;
225
226 /*
227 * The time taken by smu operation to complete is between
228 * 10us to 1ms. Sometime it may take more time.
229 * In SMP system timeout of 100 millisecs should
230 * be enough for the previous thread to finish the operation
231 */
232 ret = down_timeout(&sock->hsmp_sem, msecs_to_jiffies(HSMP_MSG_TIMEOUT));
233 if (ret < 0)
234 return ret;
235
236 ret = __hsmp_send_message(nb->root, msg);
237
238 up(&sock->hsmp_sem);
239
240 return ret;
241}
242EXPORT_SYMBOL_GPL(hsmp_send_message);
243
244static int hsmp_test(u16 sock_ind, u32 value)
245{
246 struct hsmp_message msg = { 0 };
247 struct amd_northbridge *nb;
248 int ret = -ENODEV;
249
250 nb = node_to_amd_nb(sock_ind);
251 if (!nb || !nb->root)
252 return ret;
253
254 /*
255 * Test the hsmp port by performing TEST command. The test message
256 * takes one argument and returns the value of that argument + 1.
257 */
258 msg.msg_id = HSMP_TEST;
259 msg.num_args = 1;
260 msg.response_sz = 1;
261 msg.args[0] = value;
262 msg.sock_ind = sock_ind;
263
264 ret = __hsmp_send_message(nb->root, &msg);
265 if (ret)
266 return ret;
267
268 /* Check the response value */
269 if (msg.args[0] != (value + 1)) {
270 pr_err("Socket %d test message failed, Expected 0x%08X, received 0x%08X\n",
271 sock_ind, (value + 1), msg.args[0]);
272 return -EBADE;
273 }
274
275 return ret;
276}
277
278static long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
279{
280 int __user *arguser = (int __user *)arg;
281 struct hsmp_message msg = { 0 };
282 int ret;
283
284 if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message)))
285 return -EFAULT;
286
287 /*
288 * Check msg_id is within the range of supported msg ids
289 * i.e within the array bounds of hsmp_msg_desc_table
290 */
291 if (msg.msg_id < HSMP_TEST || msg.msg_id >= HSMP_MSG_ID_MAX)
292 return -ENOMSG;
293
294 switch (fp->f_mode & (FMODE_WRITE | FMODE_READ)) {
295 case FMODE_WRITE:
296 /*
297 * Device is opened in O_WRONLY mode
298 * Execute only set/configure commands
299 */
300 if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET)
301 return -EINVAL;
302 break;
303 case FMODE_READ:
304 /*
305 * Device is opened in O_RDONLY mode
306 * Execute only get/monitor commands
307 */
308 if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET)
309 return -EINVAL;
310 break;
311 case FMODE_READ | FMODE_WRITE:
312 /*
313 * Device is opened in O_RDWR mode
314 * Execute both get/monitor and set/configure commands
315 */
316 break;
317 default:
318 return -EINVAL;
319 }
320
321 ret = hsmp_send_message(&msg);
322 if (ret)
323 return ret;
324
325 if (hsmp_msg_desc_table[msg.msg_id].response_sz > 0) {
326 /* Copy results back to user for get/monitor commands */
327 if (copy_to_user(arguser, &msg, sizeof(struct hsmp_message)))
328 return -EFAULT;
329 }
330
331 return 0;
332}
333
334static const struct file_operations hsmp_fops = {
335 .owner = THIS_MODULE,
336 .unlocked_ioctl = hsmp_ioctl,
337 .compat_ioctl = hsmp_ioctl,
338};
339
340static ssize_t hsmp_metric_tbl_read(struct file *filp, struct kobject *kobj,
341 struct bin_attribute *bin_attr, char *buf,
342 loff_t off, size_t count)
343{
344 struct hsmp_socket *sock = bin_attr->private;
345 struct hsmp_message msg = { 0 };
346 int ret;
347
348 /* Do not support lseek(), reads entire metric table */
349 if (count < bin_attr->size) {
350 dev_err(plat_dev.dev, "Wrong buffer size\n");
351 return -EINVAL;
352 }
353
354 if (!sock) {
355 dev_err(plat_dev.dev, "Failed to read attribute private data\n");
356 return -EINVAL;
357 }
358
359 msg.msg_id = HSMP_GET_METRIC_TABLE;
360 msg.sock_ind = sock->sock_ind;
361
362 ret = hsmp_send_message(&msg);
363 if (ret)
364 return ret;
365 memcpy_fromio(buf, sock->metric_tbl_addr, bin_attr->size);
366
367 return bin_attr->size;
368}
369
370static int hsmp_get_tbl_dram_base(u16 sock_ind)
371{
372 struct hsmp_socket *sock = &plat_dev.sock[sock_ind];
373 struct hsmp_message msg = { 0 };
374 phys_addr_t dram_addr;
375 int ret;
376
377 msg.sock_ind = sock_ind;
378 msg.response_sz = hsmp_msg_desc_table[HSMP_GET_METRIC_TABLE_DRAM_ADDR].response_sz;
379 msg.msg_id = HSMP_GET_METRIC_TABLE_DRAM_ADDR;
380
381 ret = hsmp_send_message(&msg);
382 if (ret)
383 return ret;
384
385 /*
386 * calculate the metric table DRAM address from lower and upper 32 bits
387 * sent from SMU and ioremap it to virtual address.
388 */
389 dram_addr = msg.args[0] | ((u64)(msg.args[1]) << 32);
390 if (!dram_addr) {
391 dev_err(plat_dev.dev, "Invalid DRAM address for metric table\n");
392 return -ENOMEM;
393 }
394 sock->metric_tbl_addr = devm_ioremap(plat_dev.dev, dram_addr,
395 sizeof(struct hsmp_metric_table));
396 if (!sock->metric_tbl_addr) {
397 dev_err(plat_dev.dev, "Failed to ioremap metric table addr\n");
398 return -ENOMEM;
399 }
400 return 0;
401}
402
403static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj,
404 struct bin_attribute *battr, int id)
405{
406 if (plat_dev.proto_ver == HSMP_PROTO_VER6)
407 return battr->attr.mode;
408 else
409 return 0;
410}
411
412static int hsmp_init_metric_tbl_bin_attr(struct bin_attribute **hattrs, u16 sock_ind)
413{
414 struct bin_attribute *hattr = &plat_dev.sock[sock_ind].hsmp_attr;
415
416 sysfs_bin_attr_init(hattr);
417 hattr->attr.name = HSMP_METRICS_TABLE_NAME;
418 hattr->attr.mode = 0444;
419 hattr->read = hsmp_metric_tbl_read;
420 hattr->size = sizeof(struct hsmp_metric_table);
421 hattr->private = &plat_dev.sock[sock_ind];
422 hattrs[0] = hattr;
423
424 if (plat_dev.proto_ver == HSMP_PROTO_VER6)
425 return (hsmp_get_tbl_dram_base(sock_ind));
426 else
427 return 0;
428}
429
430/* One bin sysfs for metrics table*/
431#define NUM_HSMP_ATTRS 1
432
433static int hsmp_create_sysfs_interface(void)
434{
435 const struct attribute_group **hsmp_attr_grps;
436 struct bin_attribute **hsmp_bin_attrs;
437 struct attribute_group *attr_grp;
438 int ret;
439 u16 i;
440
441 /* String formatting is currently limited to u8 sockets */
442 if (WARN_ON(plat_dev.num_sockets > U8_MAX))
443 return -ERANGE;
444
445 hsmp_attr_grps = devm_kzalloc(plat_dev.dev, sizeof(struct attribute_group *) *
446 (plat_dev.num_sockets + 1), GFP_KERNEL);
447 if (!hsmp_attr_grps)
448 return -ENOMEM;
449
450 /* Create a sysfs directory for each socket */
451 for (i = 0; i < plat_dev.num_sockets; i++) {
452 attr_grp = devm_kzalloc(plat_dev.dev, sizeof(struct attribute_group), GFP_KERNEL);
453 if (!attr_grp)
454 return -ENOMEM;
455
456 snprintf(plat_dev.sock[i].name, HSMP_ATTR_GRP_NAME_SIZE, "socket%u", (u8)i);
457 attr_grp->name = plat_dev.sock[i].name;
458
459 /* Null terminated list of attributes */
460 hsmp_bin_attrs = devm_kzalloc(plat_dev.dev, sizeof(struct bin_attribute *) *
461 (NUM_HSMP_ATTRS + 1), GFP_KERNEL);
462 if (!hsmp_bin_attrs)
463 return -ENOMEM;
464
465 attr_grp->bin_attrs = hsmp_bin_attrs;
466 attr_grp->is_bin_visible = hsmp_is_sock_attr_visible;
467 hsmp_attr_grps[i] = attr_grp;
468
469 /* Now create the leaf nodes */
470 ret = hsmp_init_metric_tbl_bin_attr(hsmp_bin_attrs, i);
471 if (ret)
472 return ret;
473 }
474 return devm_device_add_groups(plat_dev.dev, hsmp_attr_grps);
475}
476
477static int hsmp_cache_proto_ver(void)
478{
479 struct hsmp_message msg = { 0 };
480 int ret;
481
482 msg.msg_id = HSMP_GET_PROTO_VER;
483 msg.sock_ind = 0;
484 msg.response_sz = hsmp_msg_desc_table[HSMP_GET_PROTO_VER].response_sz;
485
486 ret = hsmp_send_message(&msg);
487 if (!ret)
488 plat_dev.proto_ver = msg.args[0];
489
490 return ret;
491}
492
493static int hsmp_pltdrv_probe(struct platform_device *pdev)
494{
495 int ret, i;
496
497 plat_dev.sock = devm_kzalloc(&pdev->dev,
498 (plat_dev.num_sockets * sizeof(struct hsmp_socket)),
499 GFP_KERNEL);
500 if (!plat_dev.sock)
501 return -ENOMEM;
502 plat_dev.dev = &pdev->dev;
503
504 for (i = 0; i < plat_dev.num_sockets; i++) {
505 sema_init(&plat_dev.sock[i].hsmp_sem, 1);
506 plat_dev.sock[i].sock_ind = i;
507 }
508
509 plat_dev.hsmp_device.name = HSMP_CDEV_NAME;
510 plat_dev.hsmp_device.minor = MISC_DYNAMIC_MINOR;
511 plat_dev.hsmp_device.fops = &hsmp_fops;
512 plat_dev.hsmp_device.parent = &pdev->dev;
513 plat_dev.hsmp_device.nodename = HSMP_DEVNODE_NAME;
514 plat_dev.hsmp_device.mode = 0644;
515
516 ret = hsmp_cache_proto_ver();
517 if (ret) {
518 dev_err(plat_dev.dev, "Failed to read HSMP protocol version\n");
519 return ret;
520 }
521
522 ret = hsmp_create_sysfs_interface();
523 if (ret)
524 dev_err(plat_dev.dev, "Failed to create HSMP sysfs interface\n");
525
526 return misc_register(&plat_dev.hsmp_device);
527}
528
529static void hsmp_pltdrv_remove(struct platform_device *pdev)
530{
531 misc_deregister(&plat_dev.hsmp_device);
532}
533
534static struct platform_driver amd_hsmp_driver = {
535 .probe = hsmp_pltdrv_probe,
536 .remove_new = hsmp_pltdrv_remove,
537 .driver = {
538 .name = DRIVER_NAME,
539 },
540};
541
542static struct platform_device *amd_hsmp_platdev;
543
544static int __init hsmp_plt_init(void)
545{
546 int ret = -ENODEV;
547 int i;
548
549 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD || boot_cpu_data.x86 < 0x19) {
550 pr_err("HSMP is not supported on Family:%x model:%x\n",
551 boot_cpu_data.x86, boot_cpu_data.x86_model);
552 return ret;
553 }
554
555 /*
556 * amd_nb_num() returns number of SMN/DF interfaces present in the system
557 * if we have N SMN/DF interfaces that ideally means N sockets
558 */
559 plat_dev.num_sockets = amd_nb_num();
560 if (plat_dev.num_sockets == 0)
561 return ret;
562
563 /* Test the hsmp interface on each socket */
564 for (i = 0; i < plat_dev.num_sockets; i++) {
565 ret = hsmp_test(i, 0xDEADBEEF);
566 if (ret) {
567 pr_err("HSMP test message failed on Fam:%x model:%x\n",
568 boot_cpu_data.x86, boot_cpu_data.x86_model);
569 pr_err("Is HSMP disabled in BIOS ?\n");
570 return ret;
571 }
572 }
573
574 ret = platform_driver_register(&amd_hsmp_driver);
575 if (ret)
576 return ret;
577
578 amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE);
579 if (!amd_hsmp_platdev) {
580 ret = -ENOMEM;
581 goto drv_unregister;
582 }
583
584 ret = platform_device_add(amd_hsmp_platdev);
585 if (ret) {
586 platform_device_put(amd_hsmp_platdev);
587 goto drv_unregister;
588 }
589
590 return 0;
591
592drv_unregister:
593 platform_driver_unregister(&amd_hsmp_driver);
594 return ret;
595}
596
597static void __exit hsmp_plt_exit(void)
598{
599 platform_device_unregister(amd_hsmp_platdev);
600 platform_driver_unregister(&amd_hsmp_driver);
601}
602
603device_initcall(hsmp_plt_init);
604module_exit(hsmp_plt_exit);
605
606MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
607MODULE_VERSION(DRIVER_VERSION);
608MODULE_LICENSE("GPL v2");