aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/asus_atk0110.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/hwmon/asus_atk0110.c')
-rw-r--r--drivers/hwmon/asus_atk0110.c339
1 files changed, 284 insertions, 55 deletions
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index fe4fa29c9219..5a3ee00c0e7d 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -35,18 +35,22 @@
35#define METHOD_OLD_ENUM_FAN "FSIF" 35#define METHOD_OLD_ENUM_FAN "FSIF"
36 36
37#define ATK_MUX_HWMON 0x00000006ULL 37#define ATK_MUX_HWMON 0x00000006ULL
38#define ATK_MUX_MGMT 0x00000011ULL
38 39
39#define ATK_CLASS_MASK 0xff000000ULL 40#define ATK_CLASS_MASK 0xff000000ULL
40#define ATK_CLASS_FREQ_CTL 0x03000000ULL 41#define ATK_CLASS_FREQ_CTL 0x03000000ULL
41#define ATK_CLASS_FAN_CTL 0x04000000ULL 42#define ATK_CLASS_FAN_CTL 0x04000000ULL
42#define ATK_CLASS_HWMON 0x06000000ULL 43#define ATK_CLASS_HWMON 0x06000000ULL
44#define ATK_CLASS_MGMT 0x11000000ULL
43 45
44#define ATK_TYPE_MASK 0x00ff0000ULL 46#define ATK_TYPE_MASK 0x00ff0000ULL
45#define HWMON_TYPE_VOLT 0x00020000ULL 47#define HWMON_TYPE_VOLT 0x00020000ULL
46#define HWMON_TYPE_TEMP 0x00030000ULL 48#define HWMON_TYPE_TEMP 0x00030000ULL
47#define HWMON_TYPE_FAN 0x00040000ULL 49#define HWMON_TYPE_FAN 0x00040000ULL
48 50
49#define HWMON_SENSOR_ID_MASK 0x0000ffffULL 51#define ATK_ELEMENT_ID_MASK 0x0000ffffULL
52
53#define ATK_EC_ID 0x11060004ULL
50 54
51enum atk_pack_member { 55enum atk_pack_member {
52 HWMON_PACK_FLAGS, 56 HWMON_PACK_FLAGS,
@@ -89,6 +93,9 @@ struct atk_data {
89 /* new inteface */ 93 /* new inteface */
90 acpi_handle enumerate_handle; 94 acpi_handle enumerate_handle;
91 acpi_handle read_handle; 95 acpi_handle read_handle;
96 acpi_handle write_handle;
97
98 bool disable_ec;
92 99
93 int voltage_count; 100 int voltage_count;
94 int temperature_count; 101 int temperature_count;
@@ -129,9 +136,22 @@ struct atk_sensor_data {
129 char const *acpi_name; 136 char const *acpi_name;
130}; 137};
131 138
132struct atk_acpi_buffer_u64 { 139/* Return buffer format:
133 union acpi_object buf; 140 * [0-3] "value" is valid flag
134 u64 value; 141 * [4-7] value
142 * [8- ] unknown stuff on newer mobos
143 */
144struct atk_acpi_ret_buffer {
145 u32 flags;
146 u32 value;
147 u8 data[];
148};
149
150/* Input buffer used for GITM and SITM methods */
151struct atk_acpi_input_buf {
152 u32 id;
153 u32 param1;
154 u32 param2;
135}; 155};
136 156
137static int atk_add(struct acpi_device *device); 157static int atk_add(struct acpi_device *device);
@@ -439,52 +459,147 @@ static int atk_read_value_old(struct atk_sensor_data *sensor, u64 *value)
439 return 0; 459 return 0;
440} 460}
441 461
442static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) 462static union acpi_object *atk_ggrp(struct atk_data *data, u16 mux)
443{ 463{
444 struct atk_data *data = sensor->data;
445 struct device *dev = &data->acpi_dev->dev; 464 struct device *dev = &data->acpi_dev->dev;
465 struct acpi_buffer buf;
466 acpi_status ret;
446 struct acpi_object_list params; 467 struct acpi_object_list params;
447 struct acpi_buffer ret;
448 union acpi_object id; 468 union acpi_object id;
449 struct atk_acpi_buffer_u64 tmp; 469 union acpi_object *pack;
450 acpi_status status;
451 470
452 id.type = ACPI_TYPE_INTEGER; 471 id.type = ACPI_TYPE_INTEGER;
453 id.integer.value = sensor->id; 472 id.integer.value = mux;
454
455 params.count = 1; 473 params.count = 1;
456 params.pointer = &id; 474 params.pointer = &id;
457 475
458 tmp.buf.type = ACPI_TYPE_BUFFER; 476 buf.length = ACPI_ALLOCATE_BUFFER;
459 tmp.buf.buffer.pointer = (u8 *)&tmp.value; 477 ret = acpi_evaluate_object(data->enumerate_handle, NULL, &params, &buf);
460 tmp.buf.buffer.length = sizeof(u64); 478 if (ret != AE_OK) {
461 ret.length = sizeof(tmp); 479 dev_err(dev, "GGRP[%#x] ACPI exception: %s\n", mux,
462 ret.pointer = &tmp; 480 acpi_format_exception(ret));
481 return ERR_PTR(-EIO);
482 }
483 pack = buf.pointer;
484 if (pack->type != ACPI_TYPE_PACKAGE) {
485 /* Execution was successful, but the id was not found */
486 ACPI_FREE(pack);
487 return ERR_PTR(-ENOENT);
488 }
489
490 if (pack->package.count < 1) {
491 dev_err(dev, "GGRP[%#x] package is too small\n", mux);
492 ACPI_FREE(pack);
493 return ERR_PTR(-EIO);
494 }
495 return pack;
496}
497
498static union acpi_object *atk_gitm(struct atk_data *data, u64 id)
499{
500 struct device *dev = &data->acpi_dev->dev;
501 struct atk_acpi_input_buf buf;
502 union acpi_object tmp;
503 struct acpi_object_list params;
504 struct acpi_buffer ret;
505 union acpi_object *obj;
506 acpi_status status;
507
508 buf.id = id;
509 buf.param1 = 0;
510 buf.param2 = 0;
463 511
512 tmp.type = ACPI_TYPE_BUFFER;
513 tmp.buffer.pointer = (u8 *)&buf;
514 tmp.buffer.length = sizeof(buf);
515
516 params.count = 1;
517 params.pointer = (void *)&tmp;
518
519 ret.length = ACPI_ALLOCATE_BUFFER;
464 status = acpi_evaluate_object_typed(data->read_handle, NULL, &params, 520 status = acpi_evaluate_object_typed(data->read_handle, NULL, &params,
465 &ret, ACPI_TYPE_BUFFER); 521 &ret, ACPI_TYPE_BUFFER);
466 if (status != AE_OK) { 522 if (status != AE_OK) {
467 dev_warn(dev, "%s: ACPI exception: %s\n", __func__, 523 dev_warn(dev, "GITM[%#llx] ACPI exception: %s\n", id,
468 acpi_format_exception(status)); 524 acpi_format_exception(status));
469 return -EIO; 525 return ERR_PTR(-EIO);
526 }
527 obj = ret.pointer;
528
529 /* Sanity check */
530 if (obj->buffer.length < 8) {
531 dev_warn(dev, "Unexpected ASBF length: %u\n",
532 obj->buffer.length);
533 ACPI_FREE(obj);
534 return ERR_PTR(-EIO);
470 } 535 }
536 return obj;
537}
471 538
472 /* Return buffer format: 539static union acpi_object *atk_sitm(struct atk_data *data,
473 * [0-3] "value" is valid flag 540 struct atk_acpi_input_buf *buf)
474 * [4-7] value 541{
475 */ 542 struct device *dev = &data->acpi_dev->dev;
476 if (!(tmp.value & 0xffffffff)) { 543 struct acpi_object_list params;
544 union acpi_object tmp;
545 struct acpi_buffer ret;
546 union acpi_object *obj;
547 acpi_status status;
548
549 tmp.type = ACPI_TYPE_BUFFER;
550 tmp.buffer.pointer = (u8 *)buf;
551 tmp.buffer.length = sizeof(*buf);
552
553 params.count = 1;
554 params.pointer = &tmp;
555
556 ret.length = ACPI_ALLOCATE_BUFFER;
557 status = acpi_evaluate_object_typed(data->write_handle, NULL, &params,
558 &ret, ACPI_TYPE_BUFFER);
559 if (status != AE_OK) {
560 dev_warn(dev, "SITM[%#x] ACPI exception: %s\n", buf->id,
561 acpi_format_exception(status));
562 return ERR_PTR(-EIO);
563 }
564 obj = ret.pointer;
565
566 /* Sanity check */
567 if (obj->buffer.length < 8) {
568 dev_warn(dev, "Unexpected ASBF length: %u\n",
569 obj->buffer.length);
570 ACPI_FREE(obj);
571 return ERR_PTR(-EIO);
572 }
573 return obj;
574}
575
576static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value)
577{
578 struct atk_data *data = sensor->data;
579 struct device *dev = &data->acpi_dev->dev;
580 union acpi_object *obj;
581 struct atk_acpi_ret_buffer *buf;
582 int err = 0;
583
584 obj = atk_gitm(data, sensor->id);
585 if (IS_ERR(obj))
586 return PTR_ERR(obj);
587
588 buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
589 if (buf->flags == 0) {
477 /* The reading is not valid, possible causes: 590 /* The reading is not valid, possible causes:
478 * - sensor failure 591 * - sensor failure
479 * - enumeration was FUBAR (and we didn't notice) 592 * - enumeration was FUBAR (and we didn't notice)
480 */ 593 */
481 dev_info(dev, "Failure: %#llx\n", tmp.value); 594 dev_warn(dev, "Read failed, sensor = %#llx\n", sensor->id);
482 return -EIO; 595 err = -EIO;
596 goto out;
483 } 597 }
484 598
485 *value = (tmp.value & 0xffffffff00000000ULL) >> 32; 599 *value = buf->value;
486 600out:
487 return 0; 601 ACPI_FREE(obj);
602 return err;
488} 603}
489 604
490static int atk_read_value(struct atk_sensor_data *sensor, u64 *value) 605static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
@@ -713,43 +828,141 @@ cleanup:
713 return ret; 828 return ret;
714} 829}
715 830
716static int atk_enumerate_new_hwmon(struct atk_data *data) 831static int atk_ec_present(struct atk_data *data)
717{ 832{
718 struct device *dev = &data->acpi_dev->dev; 833 struct device *dev = &data->acpi_dev->dev;
719 struct acpi_buffer buf;
720 acpi_status ret;
721 struct acpi_object_list params;
722 union acpi_object id;
723 union acpi_object *pack; 834 union acpi_object *pack;
724 int err; 835 union acpi_object *ec;
836 int ret;
725 int i; 837 int i;
726 838
727 dev_dbg(dev, "Enumerating hwmon sensors\n"); 839 pack = atk_ggrp(data, ATK_MUX_MGMT);
840 if (IS_ERR(pack)) {
841 if (PTR_ERR(pack) == -ENOENT) {
842 /* The MGMT class does not exists - that's ok */
843 dev_dbg(dev, "Class %#llx not found\n", ATK_MUX_MGMT);
844 return 0;
845 }
846 return PTR_ERR(pack);
847 }
728 848
729 id.type = ACPI_TYPE_INTEGER; 849 /* Search the EC */
730 id.integer.value = ATK_MUX_HWMON; 850 ec = NULL;
731 params.count = 1; 851 for (i = 0; i < pack->package.count; i++) {
732 params.pointer = &id; 852 union acpi_object *obj = &pack->package.elements[i];
853 union acpi_object *id;
733 854
734 buf.length = ACPI_ALLOCATE_BUFFER; 855 if (obj->type != ACPI_TYPE_PACKAGE)
735 ret = acpi_evaluate_object_typed(data->enumerate_handle, NULL, &params, 856 continue;
736 &buf, ACPI_TYPE_PACKAGE); 857
737 if (ret != AE_OK) { 858 id = &obj->package.elements[0];
738 dev_warn(dev, METHOD_ENUMERATE ": ACPI exception: %s\n", 859 if (id->type != ACPI_TYPE_INTEGER)
739 acpi_format_exception(ret)); 860 continue;
740 return -ENODEV; 861
862 if (id->integer.value == ATK_EC_ID) {
863 ec = obj;
864 break;
865 }
741 } 866 }
742 867
743 /* Result must be a package */ 868 ret = (ec != NULL);
744 pack = buf.pointer; 869 if (!ret)
870 /* The system has no EC */
871 dev_dbg(dev, "EC not found\n");
745 872
746 if (pack->package.count < 1) { 873 ACPI_FREE(pack);
747 dev_dbg(dev, "%s: hwmon package is too small: %d\n", __func__, 874 return ret;
748 pack->package.count); 875}
749 err = -EINVAL; 876
750 goto out; 877static int atk_ec_enabled(struct atk_data *data)
878{
879 struct device *dev = &data->acpi_dev->dev;
880 union acpi_object *obj;
881 struct atk_acpi_ret_buffer *buf;
882 int err;
883
884 obj = atk_gitm(data, ATK_EC_ID);
885 if (IS_ERR(obj)) {
886 dev_err(dev, "Unable to query EC status\n");
887 return PTR_ERR(obj);
888 }
889 buf = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
890
891 if (buf->flags == 0) {
892 dev_err(dev, "Unable to query EC status\n");
893 err = -EIO;
894 } else {
895 err = (buf->value != 0);
896 dev_dbg(dev, "EC is %sabled\n",
897 err ? "en" : "dis");
898 }
899
900 ACPI_FREE(obj);
901 return err;
902}
903
904static int atk_ec_ctl(struct atk_data *data, int enable)
905{
906 struct device *dev = &data->acpi_dev->dev;
907 union acpi_object *obj;
908 struct atk_acpi_input_buf sitm;
909 struct atk_acpi_ret_buffer *ec_ret;
910 int err = 0;
911
912 sitm.id = ATK_EC_ID;
913 sitm.param1 = enable;
914 sitm.param2 = 0;
915
916 obj = atk_sitm(data, &sitm);
917 if (IS_ERR(obj)) {
918 dev_err(dev, "Failed to %sable the EC\n",
919 enable ? "en" : "dis");
920 return PTR_ERR(obj);
921 }
922 ec_ret = (struct atk_acpi_ret_buffer *)obj->buffer.pointer;
923 if (ec_ret->flags == 0) {
924 dev_err(dev, "Failed to %sable the EC\n",
925 enable ? "en" : "dis");
926 err = -EIO;
927 } else {
928 dev_info(dev, "EC %sabled\n",
929 enable ? "en" : "dis");
930 }
931
932 ACPI_FREE(obj);
933 return err;
934}
935
936static int atk_enumerate_new_hwmon(struct atk_data *data)
937{
938 struct device *dev = &data->acpi_dev->dev;
939 union acpi_object *pack;
940 int err;
941 int i;
942
943 err = atk_ec_present(data);
944 if (err < 0)
945 return err;
946 if (err) {
947 err = atk_ec_enabled(data);
948 if (err < 0)
949 return err;
950 /* If the EC was disabled we will disable it again on unload */
951 data->disable_ec = err;
952
953 err = atk_ec_ctl(data, 1);
954 if (err) {
955 data->disable_ec = false;
956 return err;
957 }
751 } 958 }
752 959
960 dev_dbg(dev, "Enumerating hwmon sensors\n");
961
962 pack = atk_ggrp(data, ATK_MUX_HWMON);
963 if (IS_ERR(pack))
964 return PTR_ERR(pack);
965
753 for (i = 0; i < pack->package.count; i++) { 966 for (i = 0; i < pack->package.count; i++) {
754 union acpi_object *obj = &pack->package.elements[i]; 967 union acpi_object *obj = &pack->package.elements[i];
755 968
@@ -758,8 +971,7 @@ static int atk_enumerate_new_hwmon(struct atk_data *data)
758 971
759 err = data->voltage_count + data->temperature_count + data->fan_count; 972 err = data->voltage_count + data->temperature_count + data->fan_count;
760 973
761out: 974 ACPI_FREE(pack);
762 ACPI_FREE(buf.pointer);
763 return err; 975 return err;
764} 976}
765 977
@@ -895,6 +1107,15 @@ static int atk_check_new_if(struct atk_data *data)
895 } 1107 }
896 data->read_handle = ret; 1108 data->read_handle = ret;
897 1109
1110 /* De-multiplexer (write) */
1111 status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
1112 if (status != AE_OK) {
1113 dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
1114 acpi_format_exception(status));
1115 return -ENODEV;
1116 }
1117 data->write_handle = ret;
1118
898 return 0; 1119 return 0;
899} 1120}
900 1121
@@ -915,6 +1136,7 @@ static int atk_add(struct acpi_device *device)
915 data->acpi_dev = device; 1136 data->acpi_dev = device;
916 data->atk_handle = device->handle; 1137 data->atk_handle = device->handle;
917 INIT_LIST_HEAD(&data->sensor_list); 1138 INIT_LIST_HEAD(&data->sensor_list);
1139 data->disable_ec = false;
918 1140
919 buf.length = ACPI_ALLOCATE_BUFFER; 1141 buf.length = ACPI_ALLOCATE_BUFFER;
920 ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL, 1142 ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL,
@@ -973,6 +1195,8 @@ static int atk_add(struct acpi_device *device)
973cleanup: 1195cleanup:
974 atk_free_sensors(data); 1196 atk_free_sensors(data);
975out: 1197out:
1198 if (data->disable_ec)
1199 atk_ec_ctl(data, 0);
976 kfree(data); 1200 kfree(data);
977 return err; 1201 return err;
978} 1202}
@@ -988,6 +1212,11 @@ static int atk_remove(struct acpi_device *device, int type)
988 atk_free_sensors(data); 1212 atk_free_sensors(data);
989 hwmon_device_unregister(data->hwmon_dev); 1213 hwmon_device_unregister(data->hwmon_dev);
990 1214
1215 if (data->disable_ec) {
1216 if (atk_ec_ctl(data, 0))
1217 dev_err(&device->dev, "Failed to disable EC\n");
1218 }
1219
991 kfree(data); 1220 kfree(data);
992 1221
993 return 0; 1222 return 0;