[PATCH] hwmon: New driver for the Asus F8000

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



A new driver (f8000) to support the hardware monitoring features of
the Asus F8000 Super-I/O chip, together with documentation.

Signed-off-by: Jean Delvare <khali at linux-fr.org>
---
Hans, looking at the datasheet of the Asus/Fintek F8000, it appears to
have a lot in common with the F71882FG and F71862FG, in particular when
it comes to fan speed control. So maybe you will prefer to add support
to your f71882fg driver, rather than having a new driver?

 Documentation/hwmon/f8000 |   71 +++++
 drivers/hwmon/Kconfig     |   10 
 drivers/hwmon/Makefile    |    1 
 drivers/hwmon/f8000.c     |  606 +++++++++++++++++++++++++++++++++++++++++++++
 4 files changed, 688 insertions(+)

--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.28-rc7/drivers/hwmon/f8000.c	2008-12-04 14:16:48.000000000 +0100
@@ -0,0 +1,606 @@
+/*
+ * f8000.c - driver for the Asus F8000 Super-I/O chip integrated hardware
+ *           monitoring features
+ * Copyright (C) 2008  Jean Delvare <khali at linux-fr.org>
+ *
+ * The F8000 was made by Fintek for Asus.
+ *
+ * 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., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/ioport.h>
+#include <linux/io.h>
+#include <linux/bitops.h>
+#include <linux/acpi.h>
+
+static unsigned short force_id;
+module_param(force_id, ushort, 0);
+MODULE_PARM_DESC(force_id, "Override the detected device ID");
+
+static struct platform_device *pdev;
+
+#define DRVNAME "f8000"
+
+/*
+ * Super-I/O constants and functions
+ */
+
+#define F8000_LD_HWM		0x04
+
+#define SIO_REG_LDSEL		0x07	/* Logical device select */
+#define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
+#define SIO_REG_MANID		0x23	/* Fintek ID (2 bytes) */
+#define SIO_REG_ENABLE		0x30	/* Logical device enable */
+#define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
+
+#define SIO_FINTEK_ID		0x1934
+#define SIO_F8000_ID		0x0581
+
+static inline int
+superio_inb(int base, int reg)
+{
+	outb(reg, base);
+	return inb(base + 1);
+}
+
+static int
+superio_inw(int base, int reg)
+{
+	int val;
+	outb(reg++, base);
+	val = inb(base + 1) << 8;
+	outb(reg, base);
+	val |= inb(base + 1);
+	return val;
+}
+
+static inline void
+superio_select(int base, int ld)
+{
+	outb(SIO_REG_LDSEL, base);
+	outb(ld, base + 1);
+}
+
+static inline void
+superio_enter(int base)
+{
+	outb(0x87, base);
+	outb(0x87, base);
+}
+
+static inline void
+superio_exit(int base)
+{
+	outb(0xaa, base);
+}
+
+/*
+ * ISA constants
+ */
+
+#define REGION_LENGTH		8
+#define ADDR_REG_OFFSET		5
+#define DATA_REG_OFFSET		6
+
+/*
+ * Registers
+ */
+
+#define F8000_REG_CONFIG		0x01
+/* in nr from 0 to 2 (8-bit values) */
+#define F8000_REG_IN(nr)		(0x20 + (nr))
+/* fan nr from 0 to 3 (12-bit values, two registers) */
+#define F8000_REG_FAN(nr)		(0xa0 + 16 * (nr))
+/* temp nr from 0 to 2 (8-bit values) */
+#define F8000_REG_TEMP(nr)		(0x70 + 2 * (nr))
+#define F8000_REG_TEMP_HIGH(nr)		(0x81 + 2 * (nr))
+#define F8000_REG_TEMP_CRIT(nr)		(0x80 + 2 * (nr))
+
+/*
+ * Data structures and manipulation thereof
+ */
+
+struct f8000_data {
+	unsigned short addr;
+	const char *name;
+	struct device *hwmon_dev;
+
+	struct mutex update_lock;
+	char valid;		/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+	unsigned long last_limits;	/* In jiffies */
+
+	/* Register values */
+	u8 in[3];
+	u16 fan[4];
+	s8 temp[3];
+	s8 temp_high[3];
+	s8 temp_crit[3];
+};
+
+/* 16 mV/bit */
+static inline long in_from_reg(u8 reg)
+{
+	return reg * 16;
+}
+
+/* The 4 most significant bits are not used */
+static inline long fan_from_reg(u16 reg)
+{
+	reg &= 0xfff;
+	if (!reg || reg == 0xfff)
+		return 0;
+	return 1500000 / reg;
+}
+
+/* 1 degree C/bit */
+static inline long temp_from_reg(s8 reg)
+{
+	return reg * 1000;
+}
+
+/*
+ * Device I/O access
+ */
+
+/* Must be called with data->update_lock held, except during initialization */
+static u8 f8000_read8(struct f8000_data *data, u8 reg)
+{
+	outb(reg, data->addr + ADDR_REG_OFFSET);
+	return inb(data->addr + DATA_REG_OFFSET);
+}
+
+/* It is important to read the MSB first, because doing so latches the
+   value of the LSB, so we are sure both bytes belong to the same value.
+   Must be called with data->update_lock held, except during initialization */
+static u16 f8000_read16(struct f8000_data *data, u8 reg)
+{
+	u16 val;
+
+	outb(reg, data->addr + ADDR_REG_OFFSET);
+	val = inb(data->addr + DATA_REG_OFFSET) << 8;
+	outb(++reg, data->addr + ADDR_REG_OFFSET);
+	val |= inb(data->addr + DATA_REG_OFFSET);
+
+	return val;
+}
+
+static struct f8000_data *f8000_update_device(struct device *dev)
+{
+	struct f8000_data *data = dev_get_drvdata(dev);
+	int nr;
+
+	mutex_lock(&data->update_lock);
+
+	/* Limit registers cache is refreshed after 60 seconds */
+	if (time_after(jiffies, data->last_updated + 60 * HZ)
+	 || !data->valid) {
+		for (nr = 0; nr < 3; nr++) {
+			data->temp_high[nr] = f8000_read8(data,
+					      F8000_REG_TEMP_HIGH(nr));
+			data->temp_crit[nr] = f8000_read8(data,
+					      F8000_REG_TEMP_CRIT(nr));
+		}
+
+		data->last_limits = jiffies;
+	}
+
+	/* Measurement registers cache is refreshed after 1 second */
+	if (time_after(jiffies, data->last_updated + HZ)
+	 || !data->valid) {
+		for (nr = 0; nr < 3; nr++) {
+			data->in[nr] = f8000_read8(data,
+				       F8000_REG_IN(nr));
+		}
+		for (nr = 0; nr < 4; nr++) {
+			data->fan[nr] = f8000_read16(data,
+					F8000_REG_FAN(nr));
+		}
+		for (nr = 0; nr < 3; nr++) {
+			data->temp[nr] = f8000_read8(data,
+					 F8000_REG_TEMP(nr));
+		}
+
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/*
+ * Sysfs interface
+ */
+
+static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+		       char *buf)
+{
+	struct f8000_data *data = f8000_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
+}
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+			char *buf)
+{
+	struct f8000_data *data = f8000_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
+}
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+			 char *buf)
+{
+	struct f8000_data *data = f8000_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute
+			     *devattr, char *buf)
+{
+	struct f8000_data *data = f8000_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
+}
+
+static ssize_t show_temp_crit(struct device *dev, struct device_attribute
+			      *devattr, char *buf)
+{
+	struct f8000_data *data = f8000_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
+	int nr = attr->index;
+
+	return sprintf(buf, "%ld\n", temp_from_reg(data->temp_crit[nr]));
+}
+
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct f8000_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+
+static SENSOR_DEVICE_ATTR(in0_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 2);
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan, NULL, 3);
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IRUGO, show_temp_max, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_crit, S_IRUGO, show_temp_crit, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IRUGO, show_temp_max, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_crit, S_IRUGO, show_temp_crit, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IRUGO, show_temp_max, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_crit, S_IRUGO, show_temp_crit, NULL, 2);
+
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
+static struct attribute *f8000_fan_attributes[] = {
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan3_input.dev_attr.attr,
+	&sensor_dev_attr_fan4_input.dev_attr.attr,
+	NULL
+};
+
+static struct attribute *f8000_in_attributes[] = {
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	NULL
+};
+
+static struct attribute *f8000_temp_attributes[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_crit.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_crit.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_crit.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group f8000_fan_group = {
+	.attrs = f8000_fan_attributes,
+};
+
+static const struct attribute_group f8000_in_group = {
+	.attrs = f8000_in_attributes,
+};
+
+static const struct attribute_group f8000_temp_group = {
+	.attrs = f8000_temp_attributes,
+};
+
+/*
+ * Device registration and initialization
+ */
+
+static int __devinit f8000_probe(struct platform_device *pdev)
+{
+	struct f8000_data *data;
+	struct resource *res;
+	int err;
+	u8 config;
+
+	data = kzalloc(sizeof(struct f8000_data), GFP_KERNEL);
+	if (!data) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Out of memory\n");
+		goto exit;
+	}
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start + ADDR_REG_OFFSET, 2, DRVNAME)) {
+		err = -EBUSY;
+		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
+			(unsigned long)(res->start + ADDR_REG_OFFSET),
+			(unsigned long)(res->start + ADDR_REG_OFFSET + 1));
+		goto exit_free;
+	}
+	data->addr = res->start;
+	data->name = "f8000";
+	mutex_init(&data->update_lock);
+
+	platform_set_drvdata(pdev, data);
+
+	/* Configuration check */
+	config = f8000_read8(data, F8000_REG_CONFIG);
+	if (config & BIT(2)) {
+		err = -ENODEV;
+		dev_warn(&pdev->dev, "Hardware monitor is powered down\n");
+		goto exit_release_region;
+	}
+	if (!(config & (BIT(1) | BIT(0)))) {
+		err = -ENODEV;
+		dev_warn(&pdev->dev, "Monitoring is disabled\n");
+		goto exit_release_region;
+	}
+
+	/* Register sysfs interface files */
+	err = device_create_file(&pdev->dev, &dev_attr_name);
+	if (err)
+		goto exit_release_region;
+
+	if (config & BIT(1)) {
+		dev_info(&pdev->dev, "Fan monitoring is %s\n", "enabled");
+		err = sysfs_create_group(&pdev->dev.kobj, &f8000_fan_group);
+		if (err)
+			goto exit_remove_files;
+	} else {
+		dev_info(&pdev->dev, "Fan monitoring is %s\n", "disabled");
+	}
+
+	if (config & BIT(0)) {
+		dev_info(&pdev->dev, "Temperature and voltage monitoring is "
+			 "%s\n", "enabled");
+		err = sysfs_create_group(&pdev->dev.kobj, &f8000_temp_group);
+		if (err)
+			goto exit_remove_files;
+		err = sysfs_create_group(&pdev->dev.kobj, &f8000_in_group);
+		if (err)
+			goto exit_remove_files;
+	} else {
+		dev_info(&pdev->dev, "Temperature and voltage monitoring is "
+			 "%s\n", "disabled");
+	}
+
+	data->hwmon_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
+		goto exit_remove_files;
+	}
+
+	return 0;
+
+exit_remove_files:
+	sysfs_remove_group(&pdev->dev.kobj, &f8000_fan_group);
+	sysfs_remove_group(&pdev->dev.kobj, &f8000_temp_group);
+	sysfs_remove_group(&pdev->dev.kobj, &f8000_in_group);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+exit_release_region:
+	release_region(res->start + ADDR_REG_OFFSET, 2);
+exit_free:
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+exit:
+	return err;
+}
+
+static int __devexit f8000_remove(struct platform_device *pdev)
+{
+	struct f8000_data *data = platform_get_drvdata(pdev);
+	struct resource *res;
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&pdev->dev.kobj, &f8000_fan_group);
+	sysfs_remove_group(&pdev->dev.kobj, &f8000_temp_group);
+	sysfs_remove_group(&pdev->dev.kobj, &f8000_in_group);
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	platform_set_drvdata(pdev, NULL);
+	kfree(data);
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	release_region(res->start + ADDR_REG_OFFSET, 2);
+
+	return 0;
+}
+
+static struct platform_driver f8000_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= DRVNAME,
+	},
+	.probe		= f8000_probe,
+	.remove		= __devexit_p(f8000_remove),
+};
+
+static int __init f8000_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + REGION_LENGTH - 1,
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc(DRVNAME, address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		goto exit;
+	}
+
+	res.name = pdev->name;
+	err = acpi_check_resource_conflict(&res);
+	if (err)
+		goto exit_device_put;
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+ exit_device_put:
+	platform_device_put(pdev);
+ exit:
+	return err;
+}
+
+static int __init f8000_find(int sioaddr, unsigned short *address)
+{
+	int err = -ENODEV;
+	u16 devid;
+
+	superio_enter(sioaddr);
+
+	devid = superio_inw(sioaddr, SIO_REG_MANID);
+	if (devid != SIO_FINTEK_ID)
+		goto exit;
+
+	devid = force_id ? force_id : superio_inw(sioaddr, SIO_REG_DEVID);
+	switch (devid) {
+	case SIO_F8000_ID:
+		break;
+	default:
+		printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
+		       "skipping\n");
+		goto exit;
+	}
+
+	superio_select(sioaddr, F8000_LD_HWM);
+	if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
+		printk(KERN_WARNING DRVNAME ": Device not activated, "
+		       "skipping\n");
+		goto exit;
+	}
+
+	*address = superio_inw(sioaddr, SIO_REG_ADDR);
+	if (*address == 0) {
+		printk(KERN_WARNING DRVNAME ": Base address not set, "
+		       "skipping\n");
+		goto exit;
+	}
+	*address &= ~(REGION_LENGTH - 1);	/* Ignore 3 LSB */
+
+	err = 0;
+	printk(KERN_INFO DRVNAME ": Found F8000 chip at %#x\n", *address);
+
+ exit:
+	superio_exit(sioaddr);
+	return err;
+}
+
+static int __init f8000_init(void)
+{
+	int err;
+	unsigned short address;
+
+	if (f8000_find(0x4e, &address)
+	 && f8000_find(0x2e, &address))
+		return -ENODEV;
+
+	err = platform_driver_register(&f8000_driver);
+	if (err)
+		goto exit;
+
+	/* Sets global pdev as a side effect */
+	err = f8000_device_add(address);
+	if (err)
+		goto exit_driver;
+
+	return 0;
+
+ exit_driver:
+	platform_driver_unregister(&f8000_driver);
+ exit:
+	return err;
+}
+
+static void __exit f8000_exit(void)
+{
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&f8000_driver);
+}
+
+MODULE_AUTHOR("Jean Delvare <khali at linux-fr>");
+MODULE_LICENSE("GPL");
+MODULE_DESCRIPTION("F8000 hardware monitoring driver");
+
+module_init(f8000_init);
+module_exit(f8000_exit);
--- /dev/null	1970-01-01 00:00:00.000000000 +0000
+++ linux-2.6.28-rc7/Documentation/hwmon/f8000	2008-12-04 14:28:50.000000000 +0100
@@ -0,0 +1,71 @@
+Kernel driver f8000
+====================
+
+Supported chips:
+  * Asus f8000
+    Prefix: 'f8000'
+    Addresses scanned: none, address read from Super I/O config space
+    Datasheet: Available on request from Fintek
+
+Author: Jean Delvare <khali at linux-fr.org>
+
+Thanks to Aaron Huang from Fintek for providing technical documentation.
+
+
+Description
+-----------
+
+The F8000 is a Super I/O chip designed by Fintek for Asus, which includes
+hardware monitoring capabilities. It can monitor 3 internal voltages, up to
+4 fans and up to 3 temperature sensors.
+
+This chip also has fan controlling features, which are not supported by
+this driver (yet).
+
+The driver assumes that no more than one chip is present, which seems
+reasonable.
+
+
+Voltage Monitoring
+------------------
+
+Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported
+range is thus from 0 to 2.040 V. The F8000 only monitors its own voltages,
+and they are all divided by 2 internally, so that they fit in this range.
+
+This voltage input mapping is as follows:
+
+in0     VCC3	+3.3V
+in1     VSB	+3.3V Stand-By
+in2     VBAT	battery
+
+
+Fan Monitoring
+--------------
+
+Fan rotation speeds are reported as 12-bit values from a gated clock
+signal. Speeds down to 366 RPM can be measured. There is no theoretical
+high limit.
+
+The chip and driver assume 2 pulse-per-revolution fans.
+
+
+Temperature Monitoring
+----------------------
+
+Temperatures are reported in degrees Celsius. Each temperature measured
+has a high limit and a critical limit. The driver doesn't yet support
+changing these limits.
+
+One of the temperature channels is internal, the other two are external.
+The mapping is as follows:
+
+temp1   internal
+temp2   external
+temp3   external
+
+
+Fan Control
+-----------
+
+Not supported by the driver at this point.
--- linux-2.6.28-rc7.orig/drivers/hwmon/Kconfig	2008-12-04 13:28:22.000000000 +0100
+++ linux-2.6.28-rc7/drivers/hwmon/Kconfig	2008-12-04 13:59:07.000000000 +0100
@@ -238,6 +238,16 @@ config SENSORS_ASB100
 	  This driver can also be built as a module.  If so, the module
 	  will be called asb100.
 
+config SENSORS_F8000
+	tristate "Asus F8000"
+	depends on X86
+	help
+	  If you say yes here you get support for hardware monitoring
+	  features of the Asus F8000 Super-I/O chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called f8000.
+
 config SENSORS_ATXP1
 	tristate "Attansic ATXP1 VID controller"
 	depends on I2C && EXPERIMENTAL
--- linux-2.6.28-rc7.orig/drivers/hwmon/Makefile	2008-12-02 10:16:04.000000000 +0100
+++ linux-2.6.28-rc7/drivers/hwmon/Makefile	2008-12-04 13:56:52.000000000 +0100
@@ -37,6 +37,7 @@ obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_F71882FG)	+= f71882fg.o
 obj-$(CONFIG_SENSORS_F75375S)	+= f75375s.o
+obj-$(CONFIG_SENSORS_F8000)	+= f8000.o
 obj-$(CONFIG_SENSORS_FSCHER)	+= fscher.o
 obj-$(CONFIG_SENSORS_FSCHMD)	+= fschmd.o
 obj-$(CONFIG_SENSORS_FSCPOS)	+= fscpos.o


-- 
Jean Delvare




[Index of Archives]     [Linux Kernel]     [Linux Hardware Monitoring]     [Linux USB Devel]     [Linux Audio Users]     [Linux Kernel]     [Linux SCSI]     [Yosemite Backpacking]

  Powered by Linux