aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/hwmon/asus_atk0110.c
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2010-01-11 12:45:55 -0500
committerLinus Torvalds <torvalds@linux-foundation.org>2010-01-11 12:45:55 -0500
commit6102c315d896fb020550fb2481613485872978f6 (patch)
treed0afc2dca7492c65be45af869b5988053bd92f2d /drivers/hwmon/asus_atk0110.c
parenta29815a333c6c6e677294bbe5958e771d0aad3fd (diff)
parent3dd3a156355e7e6bec0dc9a0bbb6eeecbd965d50 (diff)
Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: hwmon: Make PCI device ids constant hwmon: (coretemp) Fix TjMax for Atom N450/D410/D510 CPUs hwmon: (k10temp) Blacklist more family 10h processors hwmon: (asus_atk0110) Add debugfs interface hwmon: (asus_atk0110) Refactor interface probe code hwmon: (adt7462) Fix pin 28 monitoring
Diffstat (limited to 'drivers/hwmon/asus_atk0110.c')
-rw-r--r--drivers/hwmon/asus_atk0110.c289
1 files changed, 235 insertions, 54 deletions
diff --git a/drivers/hwmon/asus_atk0110.c b/drivers/hwmon/asus_atk0110.c
index 5a3ee00c0e7d..6811346c1c62 100644
--- a/drivers/hwmon/asus_atk0110.c
+++ b/drivers/hwmon/asus_atk0110.c
@@ -5,6 +5,7 @@
5 * See COPYING in the top level directory of the kernel tree. 5 * See COPYING in the top level directory of the kernel tree.
6 */ 6 */
7 7
8#include <linux/debugfs.h>
8#include <linux/kernel.h> 9#include <linux/kernel.h>
9#include <linux/hwmon.h> 10#include <linux/hwmon.h>
10#include <linux/list.h> 11#include <linux/list.h>
@@ -101,6 +102,11 @@ struct atk_data {
101 int temperature_count; 102 int temperature_count;
102 int fan_count; 103 int fan_count;
103 struct list_head sensor_list; 104 struct list_head sensor_list;
105
106 struct {
107 struct dentry *root;
108 u32 id;
109 } debugfs;
104}; 110};
105 111
106 112
@@ -624,6 +630,187 @@ static int atk_read_value(struct atk_sensor_data *sensor, u64 *value)
624 return err; 630 return err;
625} 631}
626 632
633#ifdef CONFIG_DEBUG_FS
634static int atk_debugfs_gitm_get(void *p, u64 *val)
635{
636 struct atk_data *data = p;
637 union acpi_object *ret;
638 struct atk_acpi_ret_buffer *buf;
639 int err = 0;
640
641 if (!data->read_handle)
642 return -ENODEV;
643
644 if (!data->debugfs.id)
645 return -EINVAL;
646
647 ret = atk_gitm(data, data->debugfs.id);
648 if (IS_ERR(ret))
649 return PTR_ERR(ret);
650
651 buf = (struct atk_acpi_ret_buffer *)ret->buffer.pointer;
652 if (buf->flags)
653 *val = buf->value;
654 else
655 err = -EIO;
656
657 return err;
658}
659
660DEFINE_SIMPLE_ATTRIBUTE(atk_debugfs_gitm,
661 atk_debugfs_gitm_get,
662 NULL,
663 "0x%08llx\n")
664
665static int atk_acpi_print(char *buf, size_t sz, union acpi_object *obj)
666{
667 int ret = 0;
668
669 switch (obj->type) {
670 case ACPI_TYPE_INTEGER:
671 ret = snprintf(buf, sz, "0x%08llx\n", obj->integer.value);
672 break;
673 case ACPI_TYPE_STRING:
674 ret = snprintf(buf, sz, "%s\n", obj->string.pointer);
675 break;
676 }
677
678 return ret;
679}
680
681static void atk_pack_print(char *buf, size_t sz, union acpi_object *pack)
682{
683 int ret;
684 int i;
685
686 for (i = 0; i < pack->package.count; i++) {
687 union acpi_object *obj = &pack->package.elements[i];
688
689 ret = atk_acpi_print(buf, sz, obj);
690 if (ret >= sz)
691 break;
692 buf += ret;
693 sz -= ret;
694 }
695}
696
697static int atk_debugfs_ggrp_open(struct inode *inode, struct file *file)
698{
699 struct atk_data *data = inode->i_private;
700 char *buf = NULL;
701 union acpi_object *ret;
702 u8 cls;
703 int i;
704
705 if (!data->enumerate_handle)
706 return -ENODEV;
707 if (!data->debugfs.id)
708 return -EINVAL;
709
710 cls = (data->debugfs.id & 0xff000000) >> 24;
711 ret = atk_ggrp(data, cls);
712 if (IS_ERR(ret))
713 return PTR_ERR(ret);
714
715 for (i = 0; i < ret->package.count; i++) {
716 union acpi_object *pack = &ret->package.elements[i];
717 union acpi_object *id;
718
719 if (pack->type != ACPI_TYPE_PACKAGE)
720 continue;
721 if (!pack->package.count)
722 continue;
723 id = &pack->package.elements[0];
724 if (id->integer.value == data->debugfs.id) {
725 /* Print the package */
726 buf = kzalloc(512, GFP_KERNEL);
727 if (!buf) {
728 ACPI_FREE(ret);
729 return -ENOMEM;
730 }
731 atk_pack_print(buf, 512, pack);
732 break;
733 }
734 }
735 ACPI_FREE(ret);
736
737 if (!buf)
738 return -EINVAL;
739
740 file->private_data = buf;
741
742 return nonseekable_open(inode, file);
743}
744
745static ssize_t atk_debugfs_ggrp_read(struct file *file, char __user *buf,
746 size_t count, loff_t *pos)
747{
748 char *str = file->private_data;
749 size_t len = strlen(str);
750
751 return simple_read_from_buffer(buf, count, pos, str, len);
752}
753
754static int atk_debugfs_ggrp_release(struct inode *inode, struct file *file)
755{
756 kfree(file->private_data);
757 return 0;
758}
759
760static const struct file_operations atk_debugfs_ggrp_fops = {
761 .read = atk_debugfs_ggrp_read,
762 .open = atk_debugfs_ggrp_open,
763 .release = atk_debugfs_ggrp_release,
764};
765
766static void atk_debugfs_init(struct atk_data *data)
767{
768 struct dentry *d;
769 struct dentry *f;
770
771 data->debugfs.id = 0;
772
773 d = debugfs_create_dir("asus_atk0110", NULL);
774 if (!d || IS_ERR(d))
775 return;
776
777 f = debugfs_create_x32("id", S_IRUSR | S_IWUSR, d, &data->debugfs.id);
778 if (!f || IS_ERR(f))
779 goto cleanup;
780
781 f = debugfs_create_file("gitm", S_IRUSR, d, data,
782 &atk_debugfs_gitm);
783 if (!f || IS_ERR(f))
784 goto cleanup;
785
786 f = debugfs_create_file("ggrp", S_IRUSR, d, data,
787 &atk_debugfs_ggrp_fops);
788 if (!f || IS_ERR(f))
789 goto cleanup;
790
791 data->debugfs.root = d;
792
793 return;
794cleanup:
795 debugfs_remove_recursive(d);
796}
797
798static void atk_debugfs_cleanup(struct atk_data *data)
799{
800 debugfs_remove_recursive(data->debugfs.root);
801}
802
803#else /* CONFIG_DEBUG_FS */
804
805static void atk_debugfs_init(struct atk_data *data)
806{
807}
808
809static void atk_debugfs_cleanup(struct atk_data *data)
810{
811}
812#endif
813
627static int atk_add_sensor(struct atk_data *data, union acpi_object *obj) 814static int atk_add_sensor(struct atk_data *data, union acpi_object *obj)
628{ 815{
629 struct device *dev = &data->acpi_dev->dev; 816 struct device *dev = &data->acpi_dev->dev;
@@ -1047,76 +1234,75 @@ remove:
1047 return err; 1234 return err;
1048} 1235}
1049 1236
1050static int atk_check_old_if(struct atk_data *data) 1237static int atk_probe_if(struct atk_data *data)
1051{ 1238{
1052 struct device *dev = &data->acpi_dev->dev; 1239 struct device *dev = &data->acpi_dev->dev;
1053 acpi_handle ret; 1240 acpi_handle ret;
1054 acpi_status status; 1241 acpi_status status;
1242 int err = 0;
1055 1243
1056 /* RTMP: read temperature */ 1244 /* RTMP: read temperature */
1057 status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret); 1245 status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_TMP, &ret);
1058 if (status != AE_OK) { 1246 if (ACPI_SUCCESS(status))
1247 data->rtmp_handle = ret;
1248 else
1059 dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n", 1249 dev_dbg(dev, "method " METHOD_OLD_READ_TMP " not found: %s\n",
1060 acpi_format_exception(status)); 1250 acpi_format_exception(status));
1061 return -ENODEV;
1062 }
1063 data->rtmp_handle = ret;
1064 1251
1065 /* RVLT: read voltage */ 1252 /* RVLT: read voltage */
1066 status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret); 1253 status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_VLT, &ret);
1067 if (status != AE_OK) { 1254 if (ACPI_SUCCESS(status))
1255 data->rvlt_handle = ret;
1256 else
1068 dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n", 1257 dev_dbg(dev, "method " METHOD_OLD_READ_VLT " not found: %s\n",
1069 acpi_format_exception(status)); 1258 acpi_format_exception(status));
1070 return -ENODEV;
1071 }
1072 data->rvlt_handle = ret;
1073 1259
1074 /* RFAN: read fan status */ 1260 /* RFAN: read fan status */
1075 status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret); 1261 status = acpi_get_handle(data->atk_handle, METHOD_OLD_READ_FAN, &ret);
1076 if (status != AE_OK) { 1262 if (ACPI_SUCCESS(status))
1263 data->rfan_handle = ret;
1264 else
1077 dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n", 1265 dev_dbg(dev, "method " METHOD_OLD_READ_FAN " not found: %s\n",
1078 acpi_format_exception(status)); 1266 acpi_format_exception(status));
1079 return -ENODEV;
1080 }
1081 data->rfan_handle = ret;
1082
1083 return 0;
1084}
1085
1086static int atk_check_new_if(struct atk_data *data)
1087{
1088 struct device *dev = &data->acpi_dev->dev;
1089 acpi_handle ret;
1090 acpi_status status;
1091 1267
1092 /* Enumeration */ 1268 /* Enumeration */
1093 status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret); 1269 status = acpi_get_handle(data->atk_handle, METHOD_ENUMERATE, &ret);
1094 if (status != AE_OK) { 1270 if (ACPI_SUCCESS(status))
1271 data->enumerate_handle = ret;
1272 else
1095 dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n", 1273 dev_dbg(dev, "method " METHOD_ENUMERATE " not found: %s\n",
1096 acpi_format_exception(status)); 1274 acpi_format_exception(status));
1097 return -ENODEV;
1098 }
1099 data->enumerate_handle = ret;
1100 1275
1101 /* De-multiplexer (read) */ 1276 /* De-multiplexer (read) */
1102 status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret); 1277 status = acpi_get_handle(data->atk_handle, METHOD_READ, &ret);
1103 if (status != AE_OK) { 1278 if (ACPI_SUCCESS(status))
1279 data->read_handle = ret;
1280 else
1104 dev_dbg(dev, "method " METHOD_READ " not found: %s\n", 1281 dev_dbg(dev, "method " METHOD_READ " not found: %s\n",
1105 acpi_format_exception(status)); 1282 acpi_format_exception(status));
1106 return -ENODEV;
1107 }
1108 data->read_handle = ret;
1109 1283
1110 /* De-multiplexer (write) */ 1284 /* De-multiplexer (write) */
1111 status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret); 1285 status = acpi_get_handle(data->atk_handle, METHOD_WRITE, &ret);
1112 if (status != AE_OK) { 1286 if (ACPI_SUCCESS(status))
1113 dev_dbg(dev, "method " METHOD_READ " not found: %s\n", 1287 data->write_handle = ret;
1288 else
1289 dev_dbg(dev, "method " METHOD_WRITE " not found: %s\n",
1114 acpi_format_exception(status)); 1290 acpi_format_exception(status));
1115 return -ENODEV;
1116 }
1117 data->write_handle = ret;
1118 1291
1119 return 0; 1292 /* Check for hwmon methods: first check "old" style methods; note that
1293 * both may be present: in this case we stick to the old interface;
1294 * analysis of multiple DSDTs indicates that when both interfaces
1295 * are present the new one (GGRP/GITM) is not functional.
1296 */
1297 if (data->rtmp_handle && data->rvlt_handle && data->rfan_handle)
1298 data->old_interface = true;
1299 else if (data->enumerate_handle && data->read_handle &&
1300 data->write_handle)
1301 data->old_interface = false;
1302 else
1303 err = -ENODEV;
1304
1305 return err;
1120} 1306}
1121 1307
1122static int atk_add(struct acpi_device *device) 1308static int atk_add(struct acpi_device *device)
@@ -1155,28 +1341,19 @@ static int atk_add(struct acpi_device *device)
1155 } 1341 }
1156 ACPI_FREE(buf.pointer); 1342 ACPI_FREE(buf.pointer);
1157 1343
1158 /* Check for hwmon methods: first check "old" style methods; note that 1344 err = atk_probe_if(data);
1159 * both may be present: in this case we stick to the old interface; 1345 if (err) {
1160 * analysis of multiple DSDTs indicates that when both interfaces 1346 dev_err(&device->dev, "No usable hwmon interface detected\n");
1161 * are present the new one (GGRP/GITM) is not functional. 1347 goto out;
1162 */
1163 err = atk_check_old_if(data);
1164 if (!err) {
1165 dev_dbg(&device->dev, "Using old hwmon interface\n");
1166 data->old_interface = true;
1167 } else {
1168 err = atk_check_new_if(data);
1169 if (err)
1170 goto out;
1171
1172 dev_dbg(&device->dev, "Using new hwmon interface\n");
1173 data->old_interface = false;
1174 } 1348 }
1175 1349
1176 if (data->old_interface) 1350 if (data->old_interface) {
1351 dev_dbg(&device->dev, "Using old hwmon interface\n");
1177 err = atk_enumerate_old_hwmon(data); 1352 err = atk_enumerate_old_hwmon(data);
1178 else 1353 } else {
1354 dev_dbg(&device->dev, "Using new hwmon interface\n");
1179 err = atk_enumerate_new_hwmon(data); 1355 err = atk_enumerate_new_hwmon(data);
1356 }
1180 if (err < 0) 1357 if (err < 0)
1181 goto out; 1358 goto out;
1182 if (err == 0) { 1359 if (err == 0) {
@@ -1190,6 +1367,8 @@ static int atk_add(struct acpi_device *device)
1190 if (err) 1367 if (err)
1191 goto cleanup; 1368 goto cleanup;
1192 1369
1370 atk_debugfs_init(data);
1371
1193 device->driver_data = data; 1372 device->driver_data = data;
1194 return 0; 1373 return 0;
1195cleanup: 1374cleanup:
@@ -1208,6 +1387,8 @@ static int atk_remove(struct acpi_device *device, int type)
1208 1387
1209 device->driver_data = NULL; 1388 device->driver_data = NULL;
1210 1389
1390 atk_debugfs_cleanup(data);
1391
1211 atk_remove_files(data); 1392 atk_remove_files(data);
1212 atk_free_sensors(data); 1393 atk_free_sensors(data);
1213 hwmon_device_unregister(data->hwmon_dev); 1394 hwmon_device_unregister(data->hwmon_dev);