aboutsummaryrefslogtreecommitdiffstats
path: root/drivers
diff options
context:
space:
mode:
Diffstat (limited to 'drivers')
-rw-r--r--drivers/hwmon/asus_atk0110.c185
1 files changed, 184 insertions, 1 deletions
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 19f3fd32e10a..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;
@@ -529,6 +536,43 @@ static union acpi_object *atk_gitm(struct atk_data *data, u64 id)
529 return obj; 536 return obj;
530} 537}
531 538
539static union acpi_object *atk_sitm(struct atk_data *data,
540 struct atk_acpi_input_buf *buf)
541{
542 struct device *dev = &data->acpi_dev->dev;
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
532static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value) 576static int atk_read_value_new(struct atk_sensor_data *sensor, u64 *value)
533{ 577{
534 struct atk_data *data = sensor->data; 578 struct atk_data *data = sensor->data;
@@ -784,6 +828,111 @@ cleanup:
784 return ret; 828 return ret;
785} 829}
786 830
831static int atk_ec_present(struct atk_data *data)
832{
833 struct device *dev = &data->acpi_dev->dev;
834 union acpi_object *pack;
835 union acpi_object *ec;
836 int ret;
837 int i;
838
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 }
848
849 /* Search the EC */
850 ec = NULL;
851 for (i = 0; i < pack->package.count; i++) {
852 union acpi_object *obj = &pack->package.elements[i];
853 union acpi_object *id;
854
855 if (obj->type != ACPI_TYPE_PACKAGE)
856 continue;
857
858 id = &obj->package.elements[0];
859 if (id->type != ACPI_TYPE_INTEGER)
860 continue;
861
862 if (id->integer.value == ATK_EC_ID) {
863 ec = obj;
864 break;
865 }
866 }
867
868 ret = (ec != NULL);
869 if (!ret)
870 /* The system has no EC */
871 dev_dbg(dev, "EC not found\n");
872
873 ACPI_FREE(pack);
874 return ret;
875}
876
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
787static int atk_enumerate_new_hwmon(struct atk_data *data) 936static int atk_enumerate_new_hwmon(struct atk_data *data)
788{ 937{
789 struct device *dev = &data->acpi_dev->dev; 938 struct device *dev = &data->acpi_dev->dev;
@@ -791,6 +940,23 @@ static int atk_enumerate_new_hwmon(struct atk_data *data)
791 int err; 940 int err;
792 int i; 941 int i;
793 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 }
958 }
959
794 dev_dbg(dev, "Enumerating hwmon sensors\n"); 960 dev_dbg(dev, "Enumerating hwmon sensors\n");
795 961
796 pack = atk_ggrp(data, ATK_MUX_HWMON); 962 pack = atk_ggrp(data, ATK_MUX_HWMON);
@@ -941,6 +1107,15 @@ static int atk_check_new_if(struct atk_data *data)
941 } 1107 }
942 data->read_handle = ret; 1108 data->read_handle = ret;
943 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
944 return 0; 1119 return 0;
945} 1120}
946 1121
@@ -961,6 +1136,7 @@ static int atk_add(struct acpi_device *device)
961 data->acpi_dev = device; 1136 data->acpi_dev = device;
962 data->atk_handle = device->handle; 1137 data->atk_handle = device->handle;
963 INIT_LIST_HEAD(&data->sensor_list); 1138 INIT_LIST_HEAD(&data->sensor_list);
1139 data->disable_ec = false;
964 1140
965 buf.length = ACPI_ALLOCATE_BUFFER; 1141 buf.length = ACPI_ALLOCATE_BUFFER;
966 ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL, 1142 ret = acpi_evaluate_object_typed(data->atk_handle, BOARD_ID, NULL,
@@ -1019,6 +1195,8 @@ static int atk_add(struct acpi_device *device)
1019cleanup: 1195cleanup:
1020 atk_free_sensors(data); 1196 atk_free_sensors(data);
1021out: 1197out:
1198 if (data->disable_ec)
1199 atk_ec_ctl(data, 0);
1022 kfree(data); 1200 kfree(data);
1023 return err; 1201 return err;
1024} 1202}
@@ -1034,6 +1212,11 @@ static int atk_remove(struct acpi_device *device, int type)
1034 atk_free_sensors(data); 1212 atk_free_sensors(data);
1035 hwmon_device_unregister(data->hwmon_dev); 1213 hwmon_device_unregister(data->hwmon_dev);
1036 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
1037 kfree(data); 1220 kfree(data);
1038 1221
1039 return 0; 1222 return 0;