Back to home page

OSCL-LXR

 
 

    


0001 // SPDX-License-Identifier: GPL-2.0
0002 /*
0003  * AMD HSMP Platform Driver
0004  * Copyright (c) 2022, AMD.
0005  * All Rights Reserved.
0006  *
0007  * This file provides a device implementation for HSMP interface
0008  */
0009 
0010 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
0011 
0012 #include <asm/amd_hsmp.h>
0013 #include <asm/amd_nb.h>
0014 #include <linux/delay.h>
0015 #include <linux/io.h>
0016 #include <linux/miscdevice.h>
0017 #include <linux/module.h>
0018 #include <linux/pci.h>
0019 #include <linux/platform_device.h>
0020 #include <linux/semaphore.h>
0021 
0022 #define DRIVER_NAME     "amd_hsmp"
0023 #define DRIVER_VERSION      "1.0"
0024 
0025 /* HSMP Status / Error codes */
0026 #define HSMP_STATUS_NOT_READY   0x00
0027 #define HSMP_STATUS_OK      0x01
0028 #define HSMP_ERR_INVALID_MSG    0xFE
0029 #define HSMP_ERR_INVALID_INPUT  0xFF
0030 
0031 /* Timeout in millsec */
0032 #define HSMP_MSG_TIMEOUT    100
0033 #define HSMP_SHORT_SLEEP    1
0034 
0035 #define HSMP_WR         true
0036 #define HSMP_RD         false
0037 
0038 /*
0039  * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox
0040  * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg.
0041  * Below are required SMN address for HSMP Mailbox register offsets in SMU address space
0042  */
0043 #define SMN_HSMP_MSG_ID     0x3B10534
0044 #define SMN_HSMP_MSG_RESP   0x3B10980
0045 #define SMN_HSMP_MSG_DATA   0x3B109E0
0046 
0047 #define HSMP_INDEX_REG      0xc4
0048 #define HSMP_DATA_REG       0xc8
0049 
0050 static struct semaphore *hsmp_sem;
0051 
0052 static struct miscdevice hsmp_device;
0053 
0054 static int amd_hsmp_rdwr(struct pci_dev *root, u32 address,
0055              u32 *value, bool write)
0056 {
0057     int ret;
0058 
0059     ret = pci_write_config_dword(root, HSMP_INDEX_REG, address);
0060     if (ret)
0061         return ret;
0062 
0063     ret = (write ? pci_write_config_dword(root, HSMP_DATA_REG, *value)
0064              : pci_read_config_dword(root, HSMP_DATA_REG, value));
0065 
0066     return ret;
0067 }
0068 
0069 /*
0070  * Send a message to the HSMP port via PCI-e config space registers.
0071  *
0072  * The caller is expected to zero out any unused arguments.
0073  * If a response is expected, the number of response words should be greater than 0.
0074  *
0075  * Returns 0 for success and populates the requested number of arguments.
0076  * Returns a negative error code for failure.
0077  */
0078 static int __hsmp_send_message(struct pci_dev *root, struct hsmp_message *msg)
0079 {
0080     unsigned long timeout, short_sleep;
0081     u32 mbox_status;
0082     u32 index;
0083     int ret;
0084 
0085     /* Clear the status register */
0086     mbox_status = HSMP_STATUS_NOT_READY;
0087     ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_WR);
0088     if (ret) {
0089         pr_err("Error %d clearing mailbox status register\n", ret);
0090         return ret;
0091     }
0092 
0093     index = 0;
0094     /* Write any message arguments */
0095     while (index < msg->num_args) {
0096         ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_DATA + (index << 2),
0097                     &msg->args[index], HSMP_WR);
0098         if (ret) {
0099             pr_err("Error %d writing message argument %d\n", ret, index);
0100             return ret;
0101         }
0102         index++;
0103     }
0104 
0105     /* Write the message ID which starts the operation */
0106     ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_ID, &msg->msg_id, HSMP_WR);
0107     if (ret) {
0108         pr_err("Error %d writing message ID %u\n", ret, msg->msg_id);
0109         return ret;
0110     }
0111 
0112     /*
0113      * Depending on when the trigger write completes relative to the SMU
0114      * firmware 1 ms cycle, the operation may take from tens of us to 1 ms
0115      * to complete. Some operations may take more. Therefore we will try
0116      * a few short duration sleeps and switch to long sleeps if we don't
0117      * succeed quickly.
0118      */
0119     short_sleep = jiffies + msecs_to_jiffies(HSMP_SHORT_SLEEP);
0120     timeout = jiffies + msecs_to_jiffies(HSMP_MSG_TIMEOUT);
0121 
0122     while (time_before(jiffies, timeout)) {
0123         ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_RESP, &mbox_status, HSMP_RD);
0124         if (ret) {
0125             pr_err("Error %d reading mailbox status\n", ret);
0126             return ret;
0127         }
0128 
0129         if (mbox_status != HSMP_STATUS_NOT_READY)
0130             break;
0131         if (time_before(jiffies, short_sleep))
0132             usleep_range(50, 100);
0133         else
0134             usleep_range(1000, 2000);
0135     }
0136 
0137     if (unlikely(mbox_status == HSMP_STATUS_NOT_READY)) {
0138         return -ETIMEDOUT;
0139     } else if (unlikely(mbox_status == HSMP_ERR_INVALID_MSG)) {
0140         return -ENOMSG;
0141     } else if (unlikely(mbox_status == HSMP_ERR_INVALID_INPUT)) {
0142         return -EINVAL;
0143     } else if (unlikely(mbox_status != HSMP_STATUS_OK)) {
0144         pr_err("Message ID %u unknown failure (status = 0x%X)\n",
0145                msg->msg_id, mbox_status);
0146         return -EIO;
0147     }
0148 
0149     /*
0150      * SMU has responded OK. Read response data.
0151      * SMU reads the input arguments from eight 32 bit registers starting
0152      * from SMN_HSMP_MSG_DATA and writes the response data to the same
0153      * SMN_HSMP_MSG_DATA address.
0154      * We copy the response data if any, back to the args[].
0155      */
0156     index = 0;
0157     while (index < msg->response_sz) {
0158         ret = amd_hsmp_rdwr(root, SMN_HSMP_MSG_DATA + (index << 2),
0159                     &msg->args[index], HSMP_RD);
0160         if (ret) {
0161             pr_err("Error %d reading response %u for message ID:%u\n",
0162                    ret, index, msg->msg_id);
0163             break;
0164         }
0165         index++;
0166     }
0167 
0168     return ret;
0169 }
0170 
0171 static int validate_message(struct hsmp_message *msg)
0172 {
0173     /* msg_id against valid range of message IDs */
0174     if (msg->msg_id < HSMP_TEST || msg->msg_id >= HSMP_MSG_ID_MAX)
0175         return -ENOMSG;
0176 
0177     /* msg_id is a reserved message ID */
0178     if (hsmp_msg_desc_table[msg->msg_id].type == HSMP_RSVD)
0179         return -ENOMSG;
0180 
0181     /* num_args and response_sz against the HSMP spec */
0182     if (msg->num_args != hsmp_msg_desc_table[msg->msg_id].num_args ||
0183         msg->response_sz != hsmp_msg_desc_table[msg->msg_id].response_sz)
0184         return -EINVAL;
0185 
0186     return 0;
0187 }
0188 
0189 int hsmp_send_message(struct hsmp_message *msg)
0190 {
0191     struct amd_northbridge *nb;
0192     int ret;
0193 
0194     if (!msg)
0195         return -EINVAL;
0196 
0197     nb = node_to_amd_nb(msg->sock_ind);
0198     if (!nb || !nb->root)
0199         return -ENODEV;
0200 
0201     ret = validate_message(msg);
0202     if (ret)
0203         return ret;
0204 
0205     /*
0206      * The time taken by smu operation to complete is between
0207      * 10us to 1ms. Sometime it may take more time.
0208      * In SMP system timeout of 100 millisecs should
0209      * be enough for the previous thread to finish the operation
0210      */
0211     ret = down_timeout(&hsmp_sem[msg->sock_ind],
0212                msecs_to_jiffies(HSMP_MSG_TIMEOUT));
0213     if (ret < 0)
0214         return ret;
0215 
0216     ret = __hsmp_send_message(nb->root, msg);
0217 
0218     up(&hsmp_sem[msg->sock_ind]);
0219 
0220     return ret;
0221 }
0222 EXPORT_SYMBOL_GPL(hsmp_send_message);
0223 
0224 static int hsmp_test(u16 sock_ind, u32 value)
0225 {
0226     struct hsmp_message msg = { 0 };
0227     struct amd_northbridge *nb;
0228     int ret = -ENODEV;
0229 
0230     nb = node_to_amd_nb(sock_ind);
0231     if (!nb || !nb->root)
0232         return ret;
0233 
0234     /*
0235      * Test the hsmp port by performing TEST command. The test message
0236      * takes one argument and returns the value of that argument + 1.
0237      */
0238     msg.msg_id  = HSMP_TEST;
0239     msg.num_args    = 1;
0240     msg.response_sz = 1;
0241     msg.args[0] = value;
0242     msg.sock_ind    = sock_ind;
0243 
0244     ret = __hsmp_send_message(nb->root, &msg);
0245     if (ret)
0246         return ret;
0247 
0248     /* Check the response value */
0249     if (msg.args[0] != (value + 1)) {
0250         pr_err("Socket %d test message failed, Expected 0x%08X, received 0x%08X\n",
0251                sock_ind, (value + 1), msg.args[0]);
0252         return -EBADE;
0253     }
0254 
0255     return ret;
0256 }
0257 
0258 static long hsmp_ioctl(struct file *fp, unsigned int cmd, unsigned long arg)
0259 {
0260     int __user *arguser = (int  __user *)arg;
0261     struct hsmp_message msg = { 0 };
0262     int ret;
0263 
0264     if (copy_struct_from_user(&msg, sizeof(msg), arguser, sizeof(struct hsmp_message)))
0265         return -EFAULT;
0266 
0267     /*
0268      * Check msg_id is within the range of supported msg ids
0269      * i.e within the array bounds of hsmp_msg_desc_table
0270      */
0271     if (msg.msg_id < HSMP_TEST || msg.msg_id >= HSMP_MSG_ID_MAX)
0272         return -ENOMSG;
0273 
0274     switch (fp->f_mode & (FMODE_WRITE | FMODE_READ)) {
0275     case FMODE_WRITE:
0276         /*
0277          * Device is opened in O_WRONLY mode
0278          * Execute only set/configure commands
0279          */
0280         if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_SET)
0281             return -EINVAL;
0282         break;
0283     case FMODE_READ:
0284         /*
0285          * Device is opened in O_RDONLY mode
0286          * Execute only get/monitor commands
0287          */
0288         if (hsmp_msg_desc_table[msg.msg_id].type != HSMP_GET)
0289             return -EINVAL;
0290         break;
0291     case FMODE_READ | FMODE_WRITE:
0292         /*
0293          * Device is opened in O_RDWR mode
0294          * Execute both get/monitor and set/configure commands
0295          */
0296         break;
0297     default:
0298         return -EINVAL;
0299     }
0300 
0301     ret = hsmp_send_message(&msg);
0302     if (ret)
0303         return ret;
0304 
0305     if (hsmp_msg_desc_table[msg.msg_id].response_sz > 0) {
0306         /* Copy results back to user for get/monitor commands */
0307         if (copy_to_user(arguser, &msg, sizeof(struct hsmp_message)))
0308             return -EFAULT;
0309     }
0310 
0311     return 0;
0312 }
0313 
0314 static const struct file_operations hsmp_fops = {
0315     .owner      = THIS_MODULE,
0316     .unlocked_ioctl = hsmp_ioctl,
0317     .compat_ioctl   = hsmp_ioctl,
0318 };
0319 
0320 static int hsmp_pltdrv_probe(struct platform_device *pdev)
0321 {
0322     int i;
0323 
0324     hsmp_sem = devm_kzalloc(&pdev->dev,
0325                 (amd_nb_num() * sizeof(struct semaphore)),
0326                 GFP_KERNEL);
0327     if (!hsmp_sem)
0328         return -ENOMEM;
0329 
0330     for (i = 0; i < amd_nb_num(); i++)
0331         sema_init(&hsmp_sem[i], 1);
0332 
0333     hsmp_device.name    = "hsmp_cdev";
0334     hsmp_device.minor   = MISC_DYNAMIC_MINOR;
0335     hsmp_device.fops    = &hsmp_fops;
0336     hsmp_device.parent  = &pdev->dev;
0337     hsmp_device.nodename    = "hsmp";
0338     hsmp_device.mode    = 0644;
0339 
0340     return misc_register(&hsmp_device);
0341 }
0342 
0343 static int hsmp_pltdrv_remove(struct platform_device *pdev)
0344 {
0345     misc_deregister(&hsmp_device);
0346 
0347     return 0;
0348 }
0349 
0350 static struct platform_driver amd_hsmp_driver = {
0351     .probe      = hsmp_pltdrv_probe,
0352     .remove     = hsmp_pltdrv_remove,
0353     .driver     = {
0354         .name   = DRIVER_NAME,
0355     },
0356 };
0357 
0358 static struct platform_device *amd_hsmp_platdev;
0359 
0360 static int __init hsmp_plt_init(void)
0361 {
0362     int ret = -ENODEV;
0363     u16 num_sockets;
0364     int i;
0365 
0366     if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD || boot_cpu_data.x86 < 0x19) {
0367         pr_err("HSMP is not supported on Family:%x model:%x\n",
0368                boot_cpu_data.x86, boot_cpu_data.x86_model);
0369         return ret;
0370     }
0371 
0372     /*
0373      * amd_nb_num() returns number of SMN/DF interfaces present in the system
0374      * if we have N SMN/DF interfaces that ideally means N sockets
0375      */
0376     num_sockets = amd_nb_num();
0377     if (num_sockets == 0)
0378         return ret;
0379 
0380     /* Test the hsmp interface on each socket */
0381     for (i = 0; i < num_sockets; i++) {
0382         ret = hsmp_test(i, 0xDEADBEEF);
0383         if (ret) {
0384             pr_err("HSMP is not supported on Fam:%x model:%x\n",
0385                    boot_cpu_data.x86, boot_cpu_data.x86_model);
0386             pr_err("Or Is HSMP disabled in BIOS ?\n");
0387             return -EOPNOTSUPP;
0388         }
0389     }
0390 
0391     ret = platform_driver_register(&amd_hsmp_driver);
0392     if (ret)
0393         return ret;
0394 
0395     amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, -1);
0396     if (!amd_hsmp_platdev) {
0397         ret = -ENOMEM;
0398         goto drv_unregister;
0399     }
0400 
0401     ret = platform_device_add(amd_hsmp_platdev);
0402     if (ret) {
0403         platform_device_put(amd_hsmp_platdev);
0404         goto drv_unregister;
0405     }
0406 
0407     return 0;
0408 
0409 drv_unregister:
0410     platform_driver_unregister(&amd_hsmp_driver);
0411     return ret;
0412 }
0413 
0414 static void __exit hsmp_plt_exit(void)
0415 {
0416     platform_device_unregister(amd_hsmp_platdev);
0417     platform_driver_unregister(&amd_hsmp_driver);
0418 }
0419 
0420 device_initcall(hsmp_plt_init);
0421 module_exit(hsmp_plt_exit);
0422 
0423 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver");
0424 MODULE_VERSION(DRIVER_VERSION);
0425 MODULE_LICENSE("GPL v2");