1 // SPDX-License-Identifier: GPL-2.0-only 2 /* 3 * INT3400 thermal driver 4 * 5 * Copyright (C) 2014, Intel Corporation 6 * Authors: Zhang Rui <rui.zhang@intel.com> 7 */ 8 9 #include <linux/module.h> 10 #include <linux/platform_device.h> 11 #include <linux/acpi.h> 12 #include <linux/thermal.h> 13 #include "acpi_thermal_rel.h" 14 15 #define INT3400_THERMAL_TABLE_CHANGED 0x83 16 #define INT3400_ODVP_CHANGED 0x88 17 #define INT3400_KEEP_ALIVE 0xA0 18 19 enum int3400_thermal_uuid { 20 INT3400_THERMAL_ACTIVE = 0, 21 INT3400_THERMAL_PASSIVE_1, 22 INT3400_THERMAL_CRITICAL, 23 INT3400_THERMAL_ADAPTIVE_PERFORMANCE, 24 INT3400_THERMAL_EMERGENCY_CALL_MODE, 25 INT3400_THERMAL_PASSIVE_2, 26 INT3400_THERMAL_POWER_BOSS, 27 INT3400_THERMAL_VIRTUAL_SENSOR, 28 INT3400_THERMAL_COOLING_MODE, 29 INT3400_THERMAL_HARDWARE_DUTY_CYCLING, 30 INT3400_THERMAL_MAXIMUM_UUID, 31 }; 32 33 static char *int3400_thermal_uuids[INT3400_THERMAL_MAXIMUM_UUID] = { 34 "3A95C389-E4B8-4629-A526-C52C88626BAE", 35 "42A441D6-AE6A-462b-A84B-4A8CE79027D3", 36 "97C68AE7-15FA-499c-B8C9-5DA81D606E0A", 37 "63BE270F-1C11-48FD-A6F7-3AF253FF3E2D", 38 "5349962F-71E6-431D-9AE8-0A635B710AEE", 39 "9E04115A-AE87-4D1C-9500-0F3E340BFE75", 40 "F5A35014-C209-46A4-993A-EB56DE7530A1", 41 "6ED722A7-9240-48A5-B479-31EEF723D7CF", 42 "16CAF1B7-DD38-40ED-B1C1-1B8A1913D531", 43 "BE84BABF-C4D4-403D-B495-3128FD44dAC1", 44 }; 45 46 struct odvp_attr; 47 48 struct int3400_thermal_priv { 49 struct acpi_device *adev; 50 struct platform_device *pdev; 51 struct thermal_zone_device *thermal; 52 int art_count; 53 struct art *arts; 54 int trt_count; 55 struct trt *trts; 56 u32 uuid_bitmap; 57 int rel_misc_dev_res; 58 int current_uuid_index; 59 char *data_vault; 60 int odvp_count; 61 int *odvp; 62 u32 os_uuid_mask; 63 struct odvp_attr *odvp_attrs; 64 }; 65 66 static int evaluate_odvp(struct int3400_thermal_priv *priv); 67 68 struct odvp_attr { 69 int odvp; 70 struct int3400_thermal_priv *priv; 71 struct kobj_attribute attr; 72 }; 73 74 static ssize_t data_vault_read(struct file *file, struct kobject *kobj, 75 struct bin_attribute *attr, char *buf, loff_t off, size_t count) 76 { 77 memcpy(buf, attr->private + off, count); 78 return count; 79 } 80 81 static BIN_ATTR_RO(data_vault, 0); 82 83 static struct bin_attribute *data_attributes[] = { 84 &bin_attr_data_vault, 85 NULL, 86 }; 87 88 static ssize_t imok_store(struct device *dev, struct device_attribute *attr, 89 const char *buf, size_t count) 90 { 91 struct int3400_thermal_priv *priv = dev_get_drvdata(dev); 92 acpi_status status; 93 int input, ret; 94 95 ret = kstrtouint(buf, 10, &input); 96 if (ret) 97 return ret; 98 status = acpi_execute_simple_method(priv->adev->handle, "IMOK", input); 99 if (ACPI_FAILURE(status)) 100 return -EIO; 101 102 return count; 103 } 104 105 static DEVICE_ATTR_WO(imok); 106 107 static struct attribute *imok_attr[] = { 108 &dev_attr_imok.attr, 109 NULL 110 }; 111 112 static const struct attribute_group imok_attribute_group = { 113 .attrs = imok_attr, 114 }; 115 116 static const struct attribute_group data_attribute_group = { 117 .bin_attrs = data_attributes, 118 }; 119 120 static ssize_t available_uuids_show(struct device *dev, 121 struct device_attribute *attr, 122 char *buf) 123 { 124 struct int3400_thermal_priv *priv = dev_get_drvdata(dev); 125 int i; 126 int length = 0; 127 128 if (!priv->uuid_bitmap) 129 return sprintf(buf, "UNKNOWN\n"); 130 131 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; i++) { 132 if (priv->uuid_bitmap & (1 << i)) 133 length += scnprintf(&buf[length], 134 PAGE_SIZE - length, 135 "%s\n", 136 int3400_thermal_uuids[i]); 137 } 138 139 return length; 140 } 141 142 static ssize_t current_uuid_show(struct device *dev, 143 struct device_attribute *devattr, char *buf) 144 { 145 struct int3400_thermal_priv *priv = dev_get_drvdata(dev); 146 int i, length = 0; 147 148 if (priv->current_uuid_index > 0) 149 return sprintf(buf, "%s\n", 150 int3400_thermal_uuids[priv->current_uuid_index]); 151 152 for (i = 0; i <= INT3400_THERMAL_CRITICAL; i++) { 153 if (priv->os_uuid_mask & BIT(i)) 154 length += scnprintf(&buf[length], 155 PAGE_SIZE - length, 156 "%s\n", 157 int3400_thermal_uuids[i]); 158 } 159 160 if (length) 161 return length; 162 163 return sprintf(buf, "INVALID\n"); 164 } 165 166 static int int3400_thermal_run_osc(acpi_handle handle, char *uuid_str, int *enable) 167 { 168 u32 ret, buf[2]; 169 acpi_status status; 170 int result = 0; 171 struct acpi_osc_context context = { 172 .uuid_str = NULL, 173 .rev = 1, 174 .cap.length = 8, 175 }; 176 177 context.uuid_str = uuid_str; 178 179 buf[OSC_QUERY_DWORD] = 0; 180 buf[OSC_SUPPORT_DWORD] = *enable; 181 182 context.cap.pointer = buf; 183 184 status = acpi_run_osc(handle, &context); 185 if (ACPI_SUCCESS(status)) { 186 ret = *((u32 *)(context.ret.pointer + 4)); 187 if (ret != *enable) 188 result = -EPERM; 189 } else 190 result = -EPERM; 191 192 kfree(context.ret.pointer); 193 194 return result; 195 } 196 197 static ssize_t current_uuid_store(struct device *dev, 198 struct device_attribute *attr, 199 const char *buf, size_t count) 200 { 201 struct int3400_thermal_priv *priv = dev_get_drvdata(dev); 202 int i; 203 204 for (i = 0; i < INT3400_THERMAL_MAXIMUM_UUID; ++i) { 205 if (!strncmp(buf, int3400_thermal_uuids[i], 206 sizeof(int3400_thermal_uuids[i]) - 1)) { 207 /* 208 * If we have a list of supported UUIDs, make sure 209 * this one is supported. 210 */ 211 if (priv->uuid_bitmap & BIT(i)) { 212 priv->current_uuid_index = i; 213 return count; 214 } 215 216 /* 217 * There is support of only 3 policies via the new 218 * _OSC to inform OS capability: 219 * INT3400_THERMAL_ACTIVE 220 * INT3400_THERMAL_PASSIVE_1 221 * INT3400_THERMAL_CRITICAL 222 */ 223 224 if (i > INT3400_THERMAL_CRITICAL) 225 return -EINVAL; 226 227 priv->os_uuid_mask |= BIT(i); 228 229 break; 230 } 231 } 232 233 if (priv->os_uuid_mask) { 234 int cap, ret; 235 236 /* 237 * Capability bits: 238 * Bit 0: set to 1 to indicate DPTF is active 239 * Bi1 1: set to 1 to active cooling is supported by user space daemon 240 * Bit 2: set to 1 to passive cooling is supported by user space daemon 241 * Bit 3: set to 1 to critical trip is handled by user space daemon 242 */ 243 cap = ((priv->os_uuid_mask << 1) | 0x01); 244 ret = int3400_thermal_run_osc(priv->adev->handle, 245 "b23ba85d-c8b7-3542-88de-8de2ffcfd698", 246 &cap); 247 if (ret) 248 return ret; 249 } 250 251 return count; 252 } 253 254 static DEVICE_ATTR_RW(current_uuid); 255 static DEVICE_ATTR_RO(available_uuids); 256 static struct attribute *uuid_attrs[] = { 257 &dev_attr_available_uuids.attr, 258 &dev_attr_current_uuid.attr, 259 NULL 260 }; 261 262 static const struct attribute_group uuid_attribute_group = { 263 .attrs = uuid_attrs, 264 .name = "uuids" 265 }; 266 267 static int int3400_thermal_get_uuids(struct int3400_thermal_priv *priv) 268 { 269 struct acpi_buffer buf = { ACPI_ALLOCATE_BUFFER, NULL}; 270 union acpi_object *obja, *objb; 271 int i, j; 272 int result = 0; 273 acpi_status status; 274 275 status = acpi_evaluate_object(priv->adev->handle, "IDSP", NULL, &buf); 276 if (ACPI_FAILURE(status)) 277 return -ENODEV; 278 279 obja = (union acpi_object *)buf.pointer; 280 if (obja->type != ACPI_TYPE_PACKAGE) { 281 result = -EINVAL; 282 goto end; 283 } 284 285 for (i = 0; i < obja->package.count; i++) { 286 objb = &obja->package.elements[i]; 287 if (objb->type != ACPI_TYPE_BUFFER) { 288 result = -EINVAL; 289 goto end; 290 } 291 292 /* UUID must be 16 bytes */ 293 if (objb->buffer.length != 16) { 294 result = -EINVAL; 295 goto end; 296 } 297 298 for (j = 0; j < INT3400_THERMAL_MAXIMUM_UUID; j++) { 299 guid_t guid; 300 301 guid_parse(int3400_thermal_uuids[j], &guid); 302 if (guid_equal((guid_t *)objb->buffer.pointer, &guid)) { 303 priv->uuid_bitmap |= (1 << j); 304 break; 305 } 306 } 307 } 308 309 end: 310 kfree(buf.pointer); 311 return result; 312 } 313 314 static ssize_t odvp_show(struct kobject *kobj, struct kobj_attribute *attr, 315 char *buf) 316 { 317 struct odvp_attr *odvp_attr; 318 319 odvp_attr = container_of(attr, struct odvp_attr, attr); 320 321 return sprintf(buf, "%d\n", odvp_attr->priv->odvp[odvp_attr->odvp]); 322 } 323 324 static void cleanup_odvp(struct int3400_thermal_priv *priv) 325 { 326 int i; 327 328 if (priv->odvp_attrs) { 329 for (i = 0; i < priv->odvp_count; i++) { 330 sysfs_remove_file(&priv->pdev->dev.kobj, 331 &priv->odvp_attrs[i].attr.attr); 332 kfree(priv->odvp_attrs[i].attr.attr.name); 333 } 334 kfree(priv->odvp_attrs); 335 } 336 kfree(priv->odvp); 337 priv->odvp_count = 0; 338 } 339 340 static int evaluate_odvp(struct int3400_thermal_priv *priv) 341 { 342 struct acpi_buffer odvp = { ACPI_ALLOCATE_BUFFER, NULL }; 343 union acpi_object *obj = NULL; 344 acpi_status status; 345 int i, ret; 346 347 status = acpi_evaluate_object(priv->adev->handle, "ODVP", NULL, &odvp); 348 if (ACPI_FAILURE(status)) { 349 ret = -EINVAL; 350 goto out_err; 351 } 352 353 obj = odvp.pointer; 354 if (obj->type != ACPI_TYPE_PACKAGE) { 355 ret = -EINVAL; 356 goto out_err; 357 } 358 359 if (priv->odvp == NULL) { 360 priv->odvp_count = obj->package.count; 361 priv->odvp = kmalloc_array(priv->odvp_count, sizeof(int), 362 GFP_KERNEL); 363 if (!priv->odvp) { 364 ret = -ENOMEM; 365 goto out_err; 366 } 367 } 368 369 if (priv->odvp_attrs == NULL) { 370 priv->odvp_attrs = kcalloc(priv->odvp_count, 371 sizeof(struct odvp_attr), 372 GFP_KERNEL); 373 if (!priv->odvp_attrs) { 374 ret = -ENOMEM; 375 goto out_err; 376 } 377 for (i = 0; i < priv->odvp_count; i++) { 378 struct odvp_attr *odvp = &priv->odvp_attrs[i]; 379 380 sysfs_attr_init(&odvp->attr.attr); 381 odvp->priv = priv; 382 odvp->odvp = i; 383 odvp->attr.attr.name = kasprintf(GFP_KERNEL, 384 "odvp%d", i); 385 386 if (!odvp->attr.attr.name) { 387 ret = -ENOMEM; 388 goto out_err; 389 } 390 odvp->attr.attr.mode = 0444; 391 odvp->attr.show = odvp_show; 392 odvp->attr.store = NULL; 393 ret = sysfs_create_file(&priv->pdev->dev.kobj, 394 &odvp->attr.attr); 395 if (ret) 396 goto out_err; 397 } 398 } 399 400 for (i = 0; i < obj->package.count; i++) { 401 if (obj->package.elements[i].type == ACPI_TYPE_INTEGER) 402 priv->odvp[i] = obj->package.elements[i].integer.value; 403 } 404 405 kfree(obj); 406 return 0; 407 408 out_err: 409 cleanup_odvp(priv); 410 kfree(obj); 411 return ret; 412 } 413 414 static void int3400_notify(acpi_handle handle, 415 u32 event, 416 void *data) 417 { 418 struct int3400_thermal_priv *priv = data; 419 char *thermal_prop[5]; 420 int therm_event; 421 422 if (!priv) 423 return; 424 425 switch (event) { 426 case INT3400_THERMAL_TABLE_CHANGED: 427 therm_event = THERMAL_TABLE_CHANGED; 428 break; 429 case INT3400_KEEP_ALIVE: 430 therm_event = THERMAL_EVENT_KEEP_ALIVE; 431 break; 432 case INT3400_ODVP_CHANGED: 433 evaluate_odvp(priv); 434 therm_event = THERMAL_DEVICE_POWER_CAPABILITY_CHANGED; 435 break; 436 default: 437 /* Ignore unknown notification codes sent to INT3400 device */ 438 return; 439 } 440 441 thermal_prop[0] = kasprintf(GFP_KERNEL, "NAME=%s", priv->thermal->type); 442 thermal_prop[1] = kasprintf(GFP_KERNEL, "TEMP=%d", priv->thermal->temperature); 443 thermal_prop[2] = kasprintf(GFP_KERNEL, "TRIP="); 444 thermal_prop[3] = kasprintf(GFP_KERNEL, "EVENT=%d", therm_event); 445 thermal_prop[4] = NULL; 446 kobject_uevent_env(&priv->thermal->device.kobj, KOBJ_CHANGE, thermal_prop); 447 kfree(thermal_prop[0]); 448 kfree(thermal_prop[1]); 449 kfree(thermal_prop[2]); 450 kfree(thermal_prop[3]); 451 } 452 453 static int int3400_thermal_get_temp(struct thermal_zone_device *thermal, 454 int *temp) 455 { 456 *temp = 20 * 1000; /* faked temp sensor with 20C */ 457 return 0; 458 } 459 460 static int int3400_thermal_change_mode(struct thermal_zone_device *thermal, 461 enum thermal_device_mode mode) 462 { 463 struct int3400_thermal_priv *priv = thermal->devdata; 464 int result = 0; 465 466 if (!priv) 467 return -EINVAL; 468 469 if (mode != thermal->mode) { 470 int enabled; 471 472 if (priv->current_uuid_index < 0 || 473 priv->current_uuid_index >= INT3400_THERMAL_MAXIMUM_UUID) 474 return -EINVAL; 475 476 enabled = (mode == THERMAL_DEVICE_ENABLED); 477 result = int3400_thermal_run_osc(priv->adev->handle, 478 int3400_thermal_uuids[priv->current_uuid_index], 479 &enabled); 480 } 481 482 483 evaluate_odvp(priv); 484 485 return result; 486 } 487 488 static struct thermal_zone_device_ops int3400_thermal_ops = { 489 .get_temp = int3400_thermal_get_temp, 490 .change_mode = int3400_thermal_change_mode, 491 }; 492 493 static struct thermal_zone_params int3400_thermal_params = { 494 .governor_name = "user_space", 495 .no_hwmon = true, 496 }; 497 498 static void int3400_setup_gddv(struct int3400_thermal_priv *priv) 499 { 500 struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL }; 501 union acpi_object *obj; 502 acpi_status status; 503 504 status = acpi_evaluate_object(priv->adev->handle, "GDDV", NULL, 505 &buffer); 506 if (ACPI_FAILURE(status) || !buffer.length) 507 return; 508 509 obj = buffer.pointer; 510 if (obj->type != ACPI_TYPE_PACKAGE || obj->package.count != 1 511 || obj->package.elements[0].type != ACPI_TYPE_BUFFER) { 512 kfree(buffer.pointer); 513 return; 514 } 515 516 priv->data_vault = kmemdup(obj->package.elements[0].buffer.pointer, 517 obj->package.elements[0].buffer.length, 518 GFP_KERNEL); 519 if (!priv->data_vault) { 520 kfree(buffer.pointer); 521 return; 522 } 523 524 bin_attr_data_vault.private = priv->data_vault; 525 bin_attr_data_vault.size = obj->package.elements[0].buffer.length; 526 kfree(buffer.pointer); 527 } 528 529 static int int3400_thermal_probe(struct platform_device *pdev) 530 { 531 struct acpi_device *adev = ACPI_COMPANION(&pdev->dev); 532 struct int3400_thermal_priv *priv; 533 int result; 534 535 if (!adev) 536 return -ENODEV; 537 538 priv = kzalloc(sizeof(struct int3400_thermal_priv), GFP_KERNEL); 539 if (!priv) 540 return -ENOMEM; 541 542 priv->pdev = pdev; 543 priv->adev = adev; 544 545 result = int3400_thermal_get_uuids(priv); 546 547 /* Missing IDSP isn't fatal */ 548 if (result && result != -ENODEV) 549 goto free_priv; 550 551 priv->current_uuid_index = -1; 552 553 result = acpi_parse_art(priv->adev->handle, &priv->art_count, 554 &priv->arts, true); 555 if (result) 556 dev_dbg(&pdev->dev, "_ART table parsing error\n"); 557 558 result = acpi_parse_trt(priv->adev->handle, &priv->trt_count, 559 &priv->trts, true); 560 if (result) 561 dev_dbg(&pdev->dev, "_TRT table parsing error\n"); 562 563 platform_set_drvdata(pdev, priv); 564 565 int3400_setup_gddv(priv); 566 567 evaluate_odvp(priv); 568 569 priv->thermal = thermal_zone_device_register("INT3400 Thermal", 0, 0, 570 priv, &int3400_thermal_ops, 571 &int3400_thermal_params, 0, 0); 572 if (IS_ERR(priv->thermal)) { 573 result = PTR_ERR(priv->thermal); 574 goto free_art_trt; 575 } 576 577 priv->rel_misc_dev_res = acpi_thermal_rel_misc_device_add( 578 priv->adev->handle); 579 580 result = sysfs_create_group(&pdev->dev.kobj, &uuid_attribute_group); 581 if (result) 582 goto free_rel_misc; 583 584 if (acpi_has_method(priv->adev->handle, "IMOK")) { 585 result = sysfs_create_group(&pdev->dev.kobj, &imok_attribute_group); 586 if (result) 587 goto free_imok; 588 } 589 590 if (priv->data_vault) { 591 result = sysfs_create_group(&pdev->dev.kobj, 592 &data_attribute_group); 593 if (result) 594 goto free_uuid; 595 } 596 597 result = acpi_install_notify_handler( 598 priv->adev->handle, ACPI_DEVICE_NOTIFY, int3400_notify, 599 (void *)priv); 600 if (result) 601 goto free_sysfs; 602 603 return 0; 604 605 free_sysfs: 606 cleanup_odvp(priv); 607 if (priv->data_vault) { 608 sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group); 609 kfree(priv->data_vault); 610 } 611 free_uuid: 612 sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group); 613 free_imok: 614 sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group); 615 free_rel_misc: 616 if (!priv->rel_misc_dev_res) 617 acpi_thermal_rel_misc_device_remove(priv->adev->handle); 618 thermal_zone_device_unregister(priv->thermal); 619 free_art_trt: 620 kfree(priv->trts); 621 kfree(priv->arts); 622 free_priv: 623 kfree(priv); 624 return result; 625 } 626 627 static int int3400_thermal_remove(struct platform_device *pdev) 628 { 629 struct int3400_thermal_priv *priv = platform_get_drvdata(pdev); 630 631 acpi_remove_notify_handler( 632 priv->adev->handle, ACPI_DEVICE_NOTIFY, 633 int3400_notify); 634 635 cleanup_odvp(priv); 636 637 if (!priv->rel_misc_dev_res) 638 acpi_thermal_rel_misc_device_remove(priv->adev->handle); 639 640 if (priv->data_vault) 641 sysfs_remove_group(&pdev->dev.kobj, &data_attribute_group); 642 sysfs_remove_group(&pdev->dev.kobj, &uuid_attribute_group); 643 sysfs_remove_group(&pdev->dev.kobj, &imok_attribute_group); 644 thermal_zone_device_unregister(priv->thermal); 645 kfree(priv->data_vault); 646 kfree(priv->trts); 647 kfree(priv->arts); 648 kfree(priv); 649 return 0; 650 } 651 652 static const struct acpi_device_id int3400_thermal_match[] = { 653 {"INT3400", 0}, 654 {"INTC1040", 0}, 655 {"INTC1041", 0}, 656 {"INTC10A0", 0}, 657 {} 658 }; 659 660 MODULE_DEVICE_TABLE(acpi, int3400_thermal_match); 661 662 static struct platform_driver int3400_thermal_driver = { 663 .probe = int3400_thermal_probe, 664 .remove = int3400_thermal_remove, 665 .driver = { 666 .name = "int3400 thermal", 667 .acpi_match_table = ACPI_PTR(int3400_thermal_match), 668 }, 669 }; 670 671 module_platform_driver(int3400_thermal_driver); 672 673 MODULE_DESCRIPTION("INT3400 Thermal driver"); 674 MODULE_AUTHOR("Zhang Rui <rui.zhang@intel.com>"); 675 MODULE_LICENSE("GPL"); 676