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 an ACPI based driver implementation for HSMP interface. 8 */ 9 10 #define pr_fmt(fmt) KBUILD_MODNAME ": " fmt 11 12 #include <asm/amd_hsmp.h> 13 14 #include <linux/acpi.h> 15 #include <linux/device.h> 16 #include <linux/dev_printk.h> 17 #include <linux/ioport.h> 18 #include <linux/kstrtox.h> 19 #include <linux/module.h> 20 #include <linux/platform_device.h> 21 #include <linux/sysfs.h> 22 #include <linux/uuid.h> 23 24 #include <uapi/asm-generic/errno-base.h> 25 26 #include <asm/amd_node.h> 27 28 #include "hsmp.h" 29 30 #define DRIVER_NAME "hsmp_acpi" 31 32 /* These are the strings specified in ACPI table */ 33 #define MSG_IDOFF_STR "MsgIdOffset" 34 #define MSG_ARGOFF_STR "MsgArgOffset" 35 #define MSG_RESPOFF_STR "MsgRspOffset" 36 37 static struct hsmp_plat_device *hsmp_pdev; 38 39 static int amd_hsmp_acpi_rdwr(struct hsmp_socket *sock, u32 offset, 40 u32 *value, bool write) 41 { 42 if (write) 43 iowrite32(*value, sock->virt_base_addr + offset); 44 else 45 *value = ioread32(sock->virt_base_addr + offset); 46 47 return 0; 48 } 49 50 /* This is the UUID used for HSMP */ 51 static const guid_t acpi_hsmp_uuid = GUID_INIT(0xb74d619d, 0x5707, 0x48bd, 52 0xa6, 0x9f, 0x4e, 0xa2, 53 0x87, 0x1f, 0xc2, 0xf6); 54 55 static inline bool is_acpi_hsmp_uuid(union acpi_object *obj) 56 { 57 if (obj->type == ACPI_TYPE_BUFFER && obj->buffer.length == UUID_SIZE) 58 return guid_equal((guid_t *)obj->buffer.pointer, &acpi_hsmp_uuid); 59 60 return false; 61 } 62 63 static inline int hsmp_get_uid(struct device *dev, u16 *sock_ind) 64 { 65 char *uid; 66 67 /* 68 * UID (ID00, ID01..IDXX) is used for differentiating sockets, 69 * read it and strip the "ID" part of it and convert the remaining 70 * bytes to integer. 71 */ 72 uid = acpi_device_uid(ACPI_COMPANION(dev)); 73 74 return kstrtou16(uid + 2, 10, sock_ind); 75 } 76 77 static acpi_status hsmp_resource(struct acpi_resource *res, void *data) 78 { 79 struct hsmp_socket *sock = data; 80 struct resource r; 81 82 switch (res->type) { 83 case ACPI_RESOURCE_TYPE_FIXED_MEMORY32: 84 if (!acpi_dev_resource_memory(res, &r)) 85 return AE_ERROR; 86 if (!r.start || r.end < r.start || !(r.flags & IORESOURCE_MEM_WRITEABLE)) 87 return AE_ERROR; 88 sock->mbinfo.base_addr = r.start; 89 sock->mbinfo.size = resource_size(&r); 90 break; 91 case ACPI_RESOURCE_TYPE_END_TAG: 92 break; 93 default: 94 return AE_ERROR; 95 } 96 97 return AE_OK; 98 } 99 100 static int hsmp_read_acpi_dsd(struct hsmp_socket *sock) 101 { 102 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL }; 103 union acpi_object *guid, *mailbox_package; 104 union acpi_object *dsd; 105 acpi_status status; 106 int ret = 0; 107 int j; 108 109 status = acpi_evaluate_object_typed(ACPI_HANDLE(sock->dev), "_DSD", NULL, 110 &buf, ACPI_TYPE_PACKAGE); 111 if (ACPI_FAILURE(status)) { 112 dev_err(sock->dev, "Failed to read mailbox reg offsets from DSD table, err: %s\n", 113 acpi_format_exception(status)); 114 return -ENODEV; 115 } 116 117 dsd = buf.pointer; 118 119 /* HSMP _DSD property should contain 2 objects. 120 * 1. guid which is an acpi object of type ACPI_TYPE_BUFFER 121 * 2. mailbox which is an acpi object of type ACPI_TYPE_PACKAGE 122 * This mailbox object contains 3 more acpi objects of type 123 * ACPI_TYPE_PACKAGE for holding msgid, msgresp, msgarg offsets 124 * these packages inturn contain 2 acpi objects of type 125 * ACPI_TYPE_STRING and ACPI_TYPE_INTEGER 126 */ 127 if (!dsd || dsd->type != ACPI_TYPE_PACKAGE || dsd->package.count != 2) { 128 ret = -EINVAL; 129 goto free_buf; 130 } 131 132 guid = &dsd->package.elements[0]; 133 mailbox_package = &dsd->package.elements[1]; 134 if (!is_acpi_hsmp_uuid(guid) || mailbox_package->type != ACPI_TYPE_PACKAGE) { 135 dev_err(sock->dev, "Invalid hsmp _DSD table data\n"); 136 ret = -EINVAL; 137 goto free_buf; 138 } 139 140 for (j = 0; j < mailbox_package->package.count; j++) { 141 union acpi_object *msgobj, *msgstr, *msgint; 142 143 msgobj = &mailbox_package->package.elements[j]; 144 msgstr = &msgobj->package.elements[0]; 145 msgint = &msgobj->package.elements[1]; 146 147 /* package should have 1 string and 1 integer object */ 148 if (msgobj->type != ACPI_TYPE_PACKAGE || 149 msgstr->type != ACPI_TYPE_STRING || 150 msgint->type != ACPI_TYPE_INTEGER) { 151 ret = -EINVAL; 152 goto free_buf; 153 } 154 155 if (!strncmp(msgstr->string.pointer, MSG_IDOFF_STR, 156 msgstr->string.length)) { 157 sock->mbinfo.msg_id_off = msgint->integer.value; 158 } else if (!strncmp(msgstr->string.pointer, MSG_RESPOFF_STR, 159 msgstr->string.length)) { 160 sock->mbinfo.msg_resp_off = msgint->integer.value; 161 } else if (!strncmp(msgstr->string.pointer, MSG_ARGOFF_STR, 162 msgstr->string.length)) { 163 sock->mbinfo.msg_arg_off = msgint->integer.value; 164 } else { 165 ret = -ENOENT; 166 goto free_buf; 167 } 168 } 169 170 if (!sock->mbinfo.msg_id_off || !sock->mbinfo.msg_resp_off || 171 !sock->mbinfo.msg_arg_off) 172 ret = -EINVAL; 173 174 free_buf: 175 ACPI_FREE(buf.pointer); 176 return ret; 177 } 178 179 static int hsmp_read_acpi_crs(struct hsmp_socket *sock) 180 { 181 acpi_status status; 182 183 status = acpi_walk_resources(ACPI_HANDLE(sock->dev), METHOD_NAME__CRS, 184 hsmp_resource, sock); 185 if (ACPI_FAILURE(status)) { 186 dev_err(sock->dev, "Failed to look up MP1 base address from CRS method, err: %s\n", 187 acpi_format_exception(status)); 188 return -EINVAL; 189 } 190 if (!sock->mbinfo.base_addr || !sock->mbinfo.size) 191 return -EINVAL; 192 193 /* The mapped region should be un-cached */ 194 sock->virt_base_addr = devm_ioremap_uc(sock->dev, sock->mbinfo.base_addr, 195 sock->mbinfo.size); 196 if (!sock->virt_base_addr) { 197 dev_err(sock->dev, "Failed to ioremap MP1 base address\n"); 198 return -ENOMEM; 199 } 200 201 return 0; 202 } 203 204 /* Parse the ACPI table to read the data */ 205 static int hsmp_parse_acpi_table(struct device *dev, u16 sock_ind) 206 { 207 struct hsmp_socket *sock = &hsmp_pdev->sock[sock_ind]; 208 int ret; 209 210 sock->sock_ind = sock_ind; 211 sock->dev = dev; 212 sock->amd_hsmp_rdwr = amd_hsmp_acpi_rdwr; 213 214 sema_init(&sock->hsmp_sem, 1); 215 216 dev_set_drvdata(dev, sock); 217 218 /* Read MP1 base address from CRS method */ 219 ret = hsmp_read_acpi_crs(sock); 220 if (ret) 221 return ret; 222 223 /* Read mailbox offsets from DSD table */ 224 return hsmp_read_acpi_dsd(sock); 225 } 226 227 static ssize_t hsmp_metric_tbl_acpi_read(struct file *filp, struct kobject *kobj, 228 const struct bin_attribute *bin_attr, char *buf, 229 loff_t off, size_t count) 230 { 231 struct device *dev = container_of(kobj, struct device, kobj); 232 struct hsmp_socket *sock = dev_get_drvdata(dev); 233 234 return hsmp_metric_tbl_read(sock, buf, count); 235 } 236 237 static umode_t hsmp_is_sock_attr_visible(struct kobject *kobj, 238 const struct bin_attribute *battr, int id) 239 { 240 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) 241 return battr->attr.mode; 242 243 return 0; 244 } 245 246 static int init_acpi(struct device *dev) 247 { 248 u16 sock_ind; 249 int ret; 250 251 ret = hsmp_get_uid(dev, &sock_ind); 252 if (ret) 253 return ret; 254 if (sock_ind >= hsmp_pdev->num_sockets) 255 return -EINVAL; 256 257 ret = hsmp_parse_acpi_table(dev, sock_ind); 258 if (ret) { 259 dev_err(dev, "Failed to parse ACPI table\n"); 260 return ret; 261 } 262 263 /* Test the hsmp interface */ 264 ret = hsmp_test(sock_ind, 0xDEADBEEF); 265 if (ret) { 266 dev_err(dev, "HSMP test message failed on Fam:%x model:%x\n", 267 boot_cpu_data.x86, boot_cpu_data.x86_model); 268 dev_err(dev, "Is HSMP disabled in BIOS ?\n"); 269 return ret; 270 } 271 272 ret = hsmp_cache_proto_ver(sock_ind); 273 if (ret) { 274 dev_err(dev, "Failed to read HSMP protocol version\n"); 275 return ret; 276 } 277 278 if (hsmp_pdev->proto_ver == HSMP_PROTO_VER6) { 279 ret = hsmp_get_tbl_dram_base(sock_ind); 280 if (ret) 281 dev_err(dev, "Failed to init metric table\n"); 282 } 283 284 ret = hsmp_create_sensor(dev, sock_ind); 285 if (ret) 286 dev_err(dev, "Failed to register HSMP sensors with hwmon\n"); 287 288 return ret; 289 } 290 291 static const struct bin_attribute hsmp_metric_tbl_attr = { 292 .attr = { .name = HSMP_METRICS_TABLE_NAME, .mode = 0444}, 293 .read_new = hsmp_metric_tbl_acpi_read, 294 .size = sizeof(struct hsmp_metric_table), 295 }; 296 297 static const struct bin_attribute *hsmp_attr_list[] = { 298 &hsmp_metric_tbl_attr, 299 NULL 300 }; 301 302 static const struct attribute_group hsmp_attr_grp = { 303 .bin_attrs_new = hsmp_attr_list, 304 .is_bin_visible = hsmp_is_sock_attr_visible, 305 }; 306 307 static const struct attribute_group *hsmp_groups[] = { 308 &hsmp_attr_grp, 309 NULL 310 }; 311 312 static const struct acpi_device_id amd_hsmp_acpi_ids[] = { 313 {ACPI_HSMP_DEVICE_HID, 0}, 314 {} 315 }; 316 MODULE_DEVICE_TABLE(acpi, amd_hsmp_acpi_ids); 317 318 static int hsmp_acpi_probe(struct platform_device *pdev) 319 { 320 int ret; 321 322 hsmp_pdev = get_hsmp_pdev(); 323 if (!hsmp_pdev) 324 return -ENOMEM; 325 326 if (!hsmp_pdev->is_probed) { 327 hsmp_pdev->num_sockets = amd_num_nodes(); 328 if (hsmp_pdev->num_sockets == 0 || hsmp_pdev->num_sockets > MAX_AMD_NUM_NODES) 329 return -ENODEV; 330 331 hsmp_pdev->sock = devm_kcalloc(&pdev->dev, hsmp_pdev->num_sockets, 332 sizeof(*hsmp_pdev->sock), 333 GFP_KERNEL); 334 if (!hsmp_pdev->sock) 335 return -ENOMEM; 336 } 337 338 ret = init_acpi(&pdev->dev); 339 if (ret) { 340 dev_err(&pdev->dev, "Failed to initialize HSMP interface.\n"); 341 return ret; 342 } 343 344 if (!hsmp_pdev->is_probed) { 345 ret = hsmp_misc_register(&pdev->dev); 346 if (ret) 347 return ret; 348 hsmp_pdev->is_probed = true; 349 } 350 351 return 0; 352 } 353 354 static void hsmp_acpi_remove(struct platform_device *pdev) 355 { 356 /* 357 * We register only one misc_device even on multi-socket system. 358 * So, deregister should happen only once. 359 */ 360 if (hsmp_pdev->is_probed) { 361 hsmp_misc_deregister(); 362 hsmp_pdev->is_probed = false; 363 } 364 } 365 366 static struct platform_driver amd_hsmp_driver = { 367 .probe = hsmp_acpi_probe, 368 .remove = hsmp_acpi_remove, 369 .driver = { 370 .name = DRIVER_NAME, 371 .acpi_match_table = amd_hsmp_acpi_ids, 372 .dev_groups = hsmp_groups, 373 }, 374 }; 375 376 module_platform_driver(amd_hsmp_driver); 377 378 MODULE_IMPORT_NS("AMD_HSMP"); 379 MODULE_DESCRIPTION("AMD HSMP Platform Interface Driver"); 380 MODULE_VERSION(DRIVER_VERSION); 381 MODULE_LICENSE("GPL"); 382