Re: [lm-sensors] [RFC] ACPI based hwmon driver for ASUS

From: Alexey Starikovskiy
Date: Thu Jun 21 2007 - 15:15:51 EST


Hi,

I think you might be interested in following patch, which implements _ACPI_ driver for the same hardware...
It is only "proof of concept" at the moment, but it does main thing -- reads hwmon device using ACPI interfaces.

Regards,
Alex.

Rudolf Marek wrote:
> Hi again,
>
> Of course it is not there because I removed it myself :/ The "sensors"
> command will just produce "general parse error" this is because of the
> unknown device class (imho). So I removed that and forgot. Well now I
> have the sysfs files:
>
> /sys/class/hwmon/hwmon2/device/:
> bus fan0_min fan2_input fan3_label in0_input in1_label
> in2_max in3_min temp0_crit temp1_input
> driver fan1_input fan2_label fan3_max in0_label in1_max
> in2_min name temp0_input temp1_label
> fan0_input fan1_label fan2_max fan3_min in0_max in1_min
> in3_input path temp0_label temp1_max
> fan0_label fan1_max fan2_min hid in0_min in2_input
> in3_label power temp0_max uevent
> fan0_max fan1_min fan3_input hwmon:hwmon2 in1_input in2_label
> in3_max subsystem temp1_crit
>
>
> Please note that in kernelsrc/Documentation/hwmon/sysfs-interface
> is defined the interface. We have fans starting from 1 and not 0
> Also temperatures are in milidegrees. So your 3200 should be 32000.
> Temps file starts also from 1 and not 0. (so no temp0...)
>
> Please can you fix this issues? I will do the review later once this
> things are fixed. Values seems to match.
>
> Thanks,
> Rudolf
> -
> To unsubscribe from this list: send the line "unsubscribe linux-acpi" in
> the body of a message to majordomo@xxxxxxxxxxxxxxx
> More majordomo info at http://vger.kernel.org/majordomo-info.html
>

ASOC

From: Alexey Starikovskiy <aystarik@xxxxxxxxx>


---

drivers/acpi/Makefile | 1
drivers/acpi/asoc.c | 154 +++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 155 insertions(+), 0 deletions(-)

diff --git a/drivers/acpi/Makefile b/drivers/acpi/Makefile
index d4336f1..0e61225 100644
--- a/drivers/acpi/Makefile
+++ b/drivers/acpi/Makefile
@@ -60,3 +60,4 @@ obj-$(CONFIG_ACPI_TOSHIBA) += toshiba_acpi.o
obj-$(CONFIG_ACPI_HOTPLUG_MEMORY) += acpi_memhotplug.o
obj-y += cm_sbs.o
obj-$(CONFIG_ACPI_SBS) += sbs.o
+obj-m += asoc.o
diff --git a/drivers/acpi/asoc.c b/drivers/acpi/asoc.c
new file mode 100644
index 0000000..996ca9e
--- /dev/null
+++ b/drivers/acpi/asoc.c
@@ -0,0 +1,154 @@
+/*
+ * acpi_ac.c - ACPI ASUS hwmon driver
+ *
+ * Copyright (C) 2007 Alexey Starikovskiy <astarikovskiy@xxxxxxx>
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or (at
+ * your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful, but
+ * WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License along
+ * with this program; if not, write to the Free Software Foundation, Inc.,
+ * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
+ *
+ * ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
+ */
+
+#include <linux/kernel.h>
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/types.h>
+#include <linux/proc_fs.h>
+#include <linux/seq_file.h>
+#include <acpi/acpi_bus.h>
+#include <acpi/acpi_drivers.h>
+
+
+MODULE_AUTHOR("Alexey Starikovskiy");
+MODULE_DESCRIPTION("ACPI ASUS hwmon Driver");
+MODULE_LICENSE("GPL");
+
+static int acpi_asoc_add(struct acpi_device *device);
+static int acpi_asoc_remove(struct acpi_device *device, int type);
+
+static struct acpi_driver acpi_asoc_driver = {
+ .name = "asoc",
+ .class = "ACPI ASUS hwmon",
+ .ids = "ATK0110",
+ .ops = {
+ .add = acpi_asoc_add,
+ .remove = acpi_asoc_remove,
+ },
+};
+
+struct acpi_asoc {
+ struct acpi_device * device;
+};
+
+static acpi_status asoc_read_sif(struct acpi_device *device, char prefix)
+{
+ int i, ret = 0;
+ unsigned long value;
+ acpi_status status = 0;
+ struct acpi_buffer buffer = { ACPI_ALLOCATE_BUFFER, NULL };
+ struct acpi_buffer buffer2 = { ACPI_ALLOCATE_BUFFER, NULL };
+ union acpi_object *fsif = NULL;
+ union acpi_object *fdesc = NULL;
+ union acpi_object arg = {.type = ACPI_TYPE_INTEGER};
+ struct acpi_object_list arglist = {.count = 1, .pointer = &arg};
+ char name[5];
+
+ snprintf(name, 5, "%cSIF", prefix);
+ status = acpi_evaluate_object(device->handle, name, NULL, &buffer);
+ if (ACPI_FAILURE(status)) {
+ printk(KERN_ERR PREFIX "Evaluating %s failed, status = %d\n", name, (int)status);
+ return -ENODEV;
+ }
+
+ fsif = buffer.pointer;
+ if (!fsif || (fsif->type != ACPI_TYPE_PACKAGE) || (!fsif->package.count)) {
+ printk(KERN_ERR PREFIX "Invalid data\n");
+ ret = -EFAULT;
+ goto error;
+ }
+ for (i = 1; i < fsif->package.count; ++i) {
+ status = acpi_evaluate_object(fsif->package.elements[i].reference.handle, NULL, NULL, &buffer2);
+ if (ACPI_FAILURE(status)) {
+ printk("element evaluation failed, status = %d\n", (int)status);
+ ret = -EFAULT;
+ goto error;
+ }
+ fdesc = buffer2.pointer;
+ snprintf(name, 5, "%cGET", prefix);
+ arg.integer.value = i - 1;
+ status = acpi_evaluate_integer(device->handle, name, &arglist, &value);
+ if (ACPI_FAILURE(status)) {
+ printk("%s evaluation failed, status = %d\n", name, (int)status);
+ ret = -EFAULT;
+ kfree(buffer2.pointer);
+ goto error;
+ }
+ printk(KERN_INFO PREFIX "\"%s\" [%d,%d] = %ld\n",
+ fdesc->package.elements[1].string.pointer,
+ (int)fdesc->package.elements[2].integer.value,
+ (int)fdesc->package.elements[3].integer.value,
+ value);
+ kfree(fdesc);
+ buffer2.pointer = NULL;
+ buffer2.length = ACPI_ALLOCATE_BUFFER;
+ }
+error:
+ kfree(buffer.pointer);
+ return ret;
+}
+
+static int acpi_asoc_add(struct acpi_device *device)
+{
+ int i, result = 0;
+ acpi_status status = AE_OK;
+ struct acpi_ac *ac = NULL;
+ char prefix[] = {'V', 'T', 'F'};
+
+ if (!device)
+ return -EINVAL;
+ for (i = 0; i < 3; ++i) {
+ result = asoc_read_sif(device, prefix[i]);
+ if (result)
+ return result;
+ }
+ return result;
+}
+
+static int acpi_asoc_remove(struct acpi_device *device, int type)
+{
+ acpi_status status = AE_OK;
+
+ if (!device)
+ return -EINVAL;
+
+ return 0;
+}
+
+static int __init acpi_asoc_init(void)
+{
+ if (acpi_disabled)
+ return -ENODEV;
+ acpi_bus_register_driver(&acpi_asoc_driver);
+ return 0;
+}
+
+static void __exit acpi_asoc_exit(void)
+{
+ acpi_bus_unregister_driver(&acpi_asoc_driver);
+}
+
+module_init(acpi_asoc_init);
+module_exit(acpi_asoc_exit);