1 // SPDX-License-Identifier: GPL-2.0 2 /* 3 * AMD HSMP Platform Driver 4 * Copyright (c) 2024, AMD. 5 * All Rights Reserved. 6 * 7 * This file provides platform device implementations. 8 */ 9 10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12 #include <asm/amd_hsmp.h> 13 #include <asm/amd_nb.h> 14 15 #include <linux/device.h> 16 #include <linux/module.h> 17 #include <linux/pci.h> 18 #include <linux/platform_device.h> 19 #include <linux/sysfs.h> 20 21 #include "hsmp.h" 22 23 #define DRIVER_NAME "amd_hsmp" 24 #define DRIVER_VERSION "2.3" 25 26 /* 27 * To access specific HSMP mailbox register, s/w writes the SMN address of HSMP mailbox 28 * register into the SMN_INDEX register, and reads/writes the SMN_DATA reg. 29 * Below are required SMN address for HSMP Mailbox register offsets in SMU address space 30 */ 31 #define SMN_HSMP_BASE 0x3B00000 32 #define SMN_HSMP_MSG_ID 0x0010534 33 #define SMN_HSMP_MSG_ID_F1A_M0H 0x0010934 34 #define SMN_HSMP_MSG_RESP 0x0010980 35 #define SMN_HSMP_MSG_DATA 0x00109E0 36 37 #define HSMP_INDEX_REG 0xc4 38 #define HSMP_DATA_REG 0xc8 39 40 static struct hsmp_plat_device *hsmp_pdev; 41 42 static int amd_hsmp_pci_rdwr(struct hsmp_socket *sock, u32 offset, 43 u32 *value, bool write) 44 { 45 int ret; 46 47 if (!sock->root) 48 return -ENODEV; 49 50 ret = pci_write_config_dword(sock->root, HSMP_INDEX_REG, 51 sock->mbinfo.base_addr + offset); 52 if (ret) 53 return ret; 54 55 ret = (write ? pci_write_config_dword(sock->root, HSMP_DATA_REG, *value) 56 : pci_read_config_dword(sock->root, HSMP_DATA_REG, value)); 57 58 return ret; 59 } 60 61 static ssize_t hsmp_metric_tbl_plat_read(struct file *filp, struct kobject *kobj, 62 struct bin_attribute *bin_attr, char *buf, 63 loff_t off, size_t count) 64 { 65 struct hsmp_socket *sock; 66 u16 sock_ind; 67 68 sock_ind = (uintptr_t)bin_attr->private; 69 if (sock_ind >= hsmp_pdev->num_sockets) 70 return -EINVAL; 71 72 sock = &hsmp_pdev->sock[sock_ind]; 73 74 return hsmp_metric_tbl_read(sock, buf, count); 75 } 76 77 static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, 78 const struct bin_attribute *battr, int id) 79 { 80 u16 sock_ind; 81 82 sock_ind = (uintptr_t)battr->private; 83 84 if (id == 0 && sock_ind >= hsmp_pdev->num_sockets) 85 return SYSFS_GROUP_INVISIBLE; 86 87 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) 88 return battr->attr.mode; 89 90 return 0; 91 } 92 93 /* 94 * AMD supports maximum of 8 sockets in a system. 95 * Static array of 8 + 1(for NULL) elements is created below 96 * to create sysfs groups for sockets. 97 * is_bin_visible function is used to show / hide the necessary groups. 98 */ 99 #define HSMP_BIN_ATTR(index, _list) \ 100 static struct bin_attribute attr##index = { \ 101 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, \ 102 .private = (void *)index, \ 103 .read = hsmp_metric_tbl_plat_read, \ 104 .size = sizeof(struct hsmp_metric_table), \ 105 }; \ 106 static struct bin_attribute _list[] = { \ 107 &attr##index, \ 108 NULL \ 109 } 110 111 HSMP_BIN_ATTR(0, *sock0_attr_list); 112 HSMP_BIN_ATTR(1, *sock1_attr_list); 113 HSMP_BIN_ATTR(2, *sock2_attr_list); 114 HSMP_BIN_ATTR(3, *sock3_attr_list); 115 HSMP_BIN_ATTR(4, *sock4_attr_list); 116 HSMP_BIN_ATTR(5, *sock5_attr_list); 117 HSMP_BIN_ATTR(6, *sock6_attr_list); 118 HSMP_BIN_ATTR(7, *sock7_attr_list); 119 120 #define HSMP_BIN_ATTR_GRP(index, _list, _name) \ 121 static struct attribute_group sock##index##_attr_grp = { \ 122 .bin_attrs = _list, \ 123 .is_bin_visible = hsmp_is_sock_attr_visible, \ 124 .name = #_name, \ 125 } 126 127 HSMP_BIN_ATTR_GRP(0, sock0_attr_list, socket0); 128 HSMP_BIN_ATTR_GRP(1, sock1_attr_list, socket1); 129 HSMP_BIN_ATTR_GRP(2, sock2_attr_list, socket2); 130 HSMP_BIN_ATTR_GRP(3, sock3_attr_list, socket3); 131 HSMP_BIN_ATTR_GRP(4, sock4_attr_list, socket4); 132 HSMP_BIN_ATTR_GRP(5, sock5_attr_list, socket5); 133 HSMP_BIN_ATTR_GRP(6, sock6_attr_list, socket6); 134 HSMP_BIN_ATTR_GRP(7, sock7_attr_list, socket7); 135 136 static const struct attribute_group *hsmp_groups[] = { 137 &sock0_attr_grp, 138 &sock1_attr_grp, 139 &sock2_attr_grp, 140 &sock3_attr_grp, 141 &sock4_attr_grp, 142 &sock5_attr_grp, 143 &sock6_attr_grp, 144 &sock7_attr_grp, 145 NULL 146 }; 147 148 static inline bool is_f1a_m0h(void) 149 { 150 if (boot_cpu_data.x86 == 0x1A && boot_cpu_data.x86_model <= 0x0F) 151 return true; 152 153 return false; 154 } 155 156 static int init_platform_device(struct device *dev) 157 { 158 struct hsmp_socket *sock; 159 int ret, i; 160 161 for (i = 0; i < hsmp_pdev->num_sockets; i++) { 162 if (!node_to_amd_nb(i)) 163 return -ENODEV; 164 sock = &hsmp_pdev->sock[i]; 165 sock->root = node_to_amd_nb(i)->root; 166 sock->sock_ind = i; 167 sock->dev = dev; 168 sock->mbinfo.base_addr = SMN_HSMP_BASE; 169 sock->amd_hsmp_rdwr = amd_hsmp_pci_rdwr; 170 171 /* 172 * This is a transitional change from non-ACPI to ACPI, only 173 * family 0x1A, model 0x00 platform is supported for both ACPI and non-ACPI. 174 */ 175 if (is_f1a_m0h()) 176 sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID_F1A_M0H; 177 else 178 sock->mbinfo.msg_id_off = SMN_HSMP_MSG_ID; 179 180 sock->mbinfo.msg_resp_off = SMN_HSMP_MSG_RESP; 181 sock->mbinfo.msg_arg_off = SMN_HSMP_MSG_DATA; 182 sema_init(&sock->hsmp_sem, 1); 183 184 /* Test the hsmp interface on each socket */ 185 ret = hsmp_test(i, 0xDEADBEEF); 186 if (ret) { 187 dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n", 188 boot_cpu_data.x86, boot_cpu_data.x86_model); 189 dev_err(dev, "Is HSMP disabled in BIOS ?\n"); 190 return ret; 191 } 192 193 ret = hsmp_cache_proto_ver(i); 194 if (ret) { 195 dev_err(dev, "Failed to read HSMP protocol version\n"); 196 return ret; 197 } 198 199 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 200 ret = hsmp_get_tbl_dram_base(i); 201 if (ret) 202 dev_err(dev, "Failed to init metric table\n"); 203 } 204 } 205 206 return 0; 207 } 208 209 static int hsmp_pltdrv_probe(struct platform_device *pdev) 210 { 211 int ret; 212 213 hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, 214 sizeof(*hsmp_pdev->sock), 215 GFP_KERNEL); 216 if (!hsmp_pdev->sock) 217 return -ENOMEM; 218 219 ret = init_platform_device(&pdev->dev); 220 if (ret) { 221 dev_err(&pdev->dev, "Failed to init HSMP mailbox\n"); 222 return ret; 223 } 224 225 return hsmp_misc_register(&pdev->dev); 226 } 227 228 static void hsmp_pltdrv_remove(struct platform_device *pdev) 229 { 230 hsmp_misc_deregister(); 231 } 232 233 static struct platform_driver amd_hsmp_driver = { 234 .probe = hsmp_pltdrv_probe, 235 .remove = hsmp_pltdrv_remove, 236 .driver = { 237 .name = DRIVER_NAME, 238 .dev_groups = hsmp_groups, 239 }, 240 }; 241 242 static struct platform_device *amd_hsmp_platdev; 243 244 static int hsmp_plat_dev_register(void) 245 { 246 int ret; 247 248 amd_hsmp_platdev = platform_device_alloc(DRIVER_NAME, PLATFORM_DEVID_NONE); 249 if (!amd_hsmp_platdev) 250 return -ENOMEM; 251 252 ret = platform_device_add(amd_hsmp_platdev); 253 if (ret) 254 platform_device_put(amd_hsmp_platdev); 255 256 return ret; 257 } 258 259 /* 260 * This check is only needed for backward compatibility of previous platforms. 261 * All new platforms are expected to support ACPI based probing. 262 */ 263 static bool legacy_hsmp_support(void) 264 { 265 if (boot_cpu_data.x86_vendor != X86_VENDOR_AMD) 266 return false; 267 268 switch (boot_cpu_data.x86) { 269 case 0x19: 270 switch (boot_cpu_data.x86_model) { 271 case 0x00 ... 0x1F: 272 case 0x30 ... 0x3F: 273 case 0x90 ... 0x9F: 274 case 0xA0 ... 0xAF: 275 return true; 276 default: 277 return false; 278 } 279 case 0x1A: 280 switch (boot_cpu_data.x86_model) { 281 case 0x00 ... 0x1F: 282 return true; 283 default: 284 return false; 285 } 286 default: 287 return false; 288 } 289 290 return false; 291 } 292 293 static int __init hsmp_plt_init(void) 294 { 295 int ret = -ENODEV; 296 297 if (!legacy_hsmp_support()) { 298 pr_info("HSMP is not supported on Family:%x model:%x\n", 299 boot_cpu_data.x86, boot_cpu_data.x86_model); 300 return ret; 301 } 302 303 hsmp_pdev = get_hsmp_pdev(); 304 if (!hsmp_pdev) 305 return -ENOMEM; 306 307 /* 308 * amd_nb_num() returns number of SMN/DF interfaces present in the system 309 * if we have N SMN/DF interfaces that ideally means N sockets 310 */ 311 hsmp_pdev->num_sockets = amd_nb_num(); 312 if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_SOCKETS) 313 return ret; 314 315 ret = platform_driver_register(&amd_hsmp_driver); 316 if (ret) 317 return ret; 318 319 ret = hsmp_plat_dev_register(); 320 if (ret) 321 platform_driver_unregister(&amd_hsmp_driver); 322 323 return ret; 324 } 325 326 static void __exit hsmp_plt_exit(void) 327 { 328 platform_device_unregister(amd_hsmp_platdev); 329 platform_driver_unregister(&amd_hsmp_driver); 330 } 331 332 device_initcall(hsmp_plt_init); 333 module_exit(hsmp_plt_exit); 334 335 MODULE_IMPORT_NS(AMD_HSMP); 336 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 337 MODULE_VERSION(DRIVER_VERSION); 338 MODULE_LICENSE("GPL"); 339