GNU Linux-libre 5.19-rc6-gnu
[releases.git] / drivers / platform / x86 / amd_hsmp.c
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
50 static struct semaphore *hsmp_sem;
51
52 static struct miscdevice hsmp_device;
53
54 static 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  */
78 static 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
171 static 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
189 int 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 }
222 EXPORT_SYMBOL_GPL(hsmp_send_message);
223
224 static 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
258 static 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
314 static const struct file_operations hsmp_fops = {
315         .owner          = THIS_MODULE,
316         .unlocked_ioctl = hsmp_ioctl,
317         .compat_ioctl   = hsmp_ioctl,
318 };
319
320 static 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
343 static int hsmp_pltdrv_remove(struct platform_device *pdev)
344 {
345         misc_deregister(&hsmp_device);
346
347         return 0;
348 }
349
350 static 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
358 static struct platform_device *amd_hsmp_platdev;
359
360 static 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
409 drv_unregister:
410         platform_driver_unregister(&amd_hsmp_driver);
411         return ret;
412 }
413
414 static void __exit hsmp_plt_exit(void)
415 {
416         platform_device_unregister(amd_hsmp_platdev);
417         platform_driver_unregister(&amd_hsmp_driver);
418 }
419
420 device_initcall(hsmp_plt_init);
421 module_exit(hsmp_plt_exit);
422
423 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
424 MODULE_VERSION(DRIVER_VERSION);
425 MODULE_LICENSE("GPL v2");