summary refs log tree commit diff
path: root/drivers/hwmon
diff options
context:
space:
mode:
authorDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-12 21:27:47 -0400
committerDmitry Torokhov <dmitry.torokhov@gmail.com>2007-10-12 21:27:47 -0400
commitb981d8b3f5e008ff10d993be633ad00564fc22cd (patch)
treee292dc07b22308912cf6a58354a608b9e5e8e1fd /drivers/hwmon
parentb11d2127c4893a7315d1e16273bc8560049fa3ca (diff)
parent2b9e0aae1d50e880c58d46788e5e3ebd89d75d62 (diff)
downloadlinux-b981d8b3f5e008ff10d993be633ad00564fc22cd.tar.gz
Merge master.kernel.org:/pub/scm/linux/kernel/git/torvalds/linux-2.6
Conflicts:

	drivers/macintosh/adbhid.c
Diffstat (limited to 'drivers/hwmon')
-rw-r--r--drivers/hwmon/Kconfig92
-rw-r--r--drivers/hwmon/Makefile4
-rw-r--r--drivers/hwmon/abituguru.c45
-rw-r--r--drivers/hwmon/abituguru3.c1141
-rw-r--r--drivers/hwmon/ams/ams-core.c1
-rw-r--r--drivers/hwmon/applesmc.c16
-rw-r--r--drivers/hwmon/coretemp.c2
-rw-r--r--drivers/hwmon/dme1737.c2080
-rw-r--r--drivers/hwmon/ds1621.c161
-rw-r--r--drivers/hwmon/f71805f.c178
-rw-r--r--drivers/hwmon/fscher.c4
-rw-r--r--drivers/hwmon/hdaps.c4
-rw-r--r--drivers/hwmon/it87.c497
-rw-r--r--drivers/hwmon/lm63.c4
-rw-r--r--drivers/hwmon/lm78.c4
-rw-r--r--drivers/hwmon/lm83.c12
-rw-r--r--drivers/hwmon/lm90.c78
-rw-r--r--drivers/hwmon/lm93.c2655
-rw-r--r--drivers/hwmon/pc87360.c232
-rw-r--r--drivers/hwmon/pc87427.c2
-rw-r--r--drivers/hwmon/sis5595.c510
-rw-r--r--drivers/hwmon/smsc47b397.c7
-rw-r--r--drivers/hwmon/smsc47m1.c16
-rw-r--r--drivers/hwmon/smsc47m192.c37
-rw-r--r--drivers/hwmon/thmc50.c440
-rw-r--r--drivers/hwmon/via686a.c538
-rw-r--r--drivers/hwmon/vt8231.c318
-rw-r--r--drivers/hwmon/w83627ehf.c661
-rw-r--r--drivers/hwmon/w83627hf.c155
-rw-r--r--drivers/hwmon/w83781d.c6
30 files changed, 8456 insertions, 1444 deletions
diff --git a/drivers/hwmon/Kconfig b/drivers/hwmon/Kconfig
index 99c82b1af8c9..e8f44b580f0a 100644
--- a/drivers/hwmon/Kconfig
+++ b/drivers/hwmon/Kconfig
@@ -29,17 +29,34 @@ config HWMON_VID
 	default n
 
 config SENSORS_ABITUGURU
-	tristate "Abit uGuru"
+	tristate "Abit uGuru (rev 1 & 2)"
 	depends on EXPERIMENTAL
 	help
-	  If you say yes here you get support for the Abit uGuru chips
-	  sensor part. The voltage and frequency control parts of the Abit
-	  uGuru are not supported. The Abit uGuru chip can be found on Abit
-	  uGuru featuring motherboards (most modern Abit motherboards).
+	  If you say yes here you get support for the sensor part of the first
+	  and second revision of the Abit uGuru chip. The voltage and frequency
+	  control parts of the Abit uGuru are not supported. The Abit uGuru
+	  chip can be found on Abit uGuru featuring motherboards (most modern
+	  Abit motherboards from before end 2005). For more info and a list
+	  of which motherboards have which revision see
+	  Documentation/hwmon/abituguru
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called abituguru.
 
+config SENSORS_ABITUGURU3
+	tristate "Abit uGuru (rev 3)"
+	depends on HWMON && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the sensor part of the
+	  third revision of the Abit uGuru chip. Only reading the sensors
+	  and their settings is supported. The third revision of the Abit
+	  uGuru chip can be found on recent Abit motherboards (since end
+	  2005). For more info and a list of which motherboards have which
+	  revision see Documentation/hwmon/abituguru3
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called abituguru3.
+
 config SENSORS_AD7418
 	tristate "Analog Devices AD7416, AD7417 and AD7418"
 	depends on I2C && EXPERIMENTAL
@@ -251,12 +268,10 @@ config SENSORS_CORETEMP
 
 config SENSORS_IT87
 	tristate "ITE IT87xx and compatibles"
-	depends on I2C
-	select I2C_ISA
 	select HWMON_VID
 	help
 	  If you say yes here you get support for ITE IT8705F, IT8712F,
-	  IT8716F and IT8718F sensor chips, and the SiS960 clone.
+	  IT8716F, IT8718F and IT8726F sensor chips, and the SiS960 clone.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called it87.
@@ -366,8 +381,8 @@ config SENSORS_LM90
 	depends on I2C
 	help
 	  If you say yes here you get support for National Semiconductor LM90,
-	  LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657 and
-	  MAX6658 sensor chips.
+	  LM86, LM89 and LM99, Analog Devices ADM1032 and Maxim MAX6657,
+	  MAX6658, MAX6659, MAX6680 and MAX6681 sensor chips.
 
 	  The Analog Devices ADT7461 sensor chip is also supported, but only
 	  if found in ADM1032 compatibility mode.
@@ -385,6 +400,17 @@ config SENSORS_LM92
 	  This driver can also be built as a module.  If so, the module
 	  will be called lm92.
 
+config SENSORS_LM93
+	tristate "National Semiconductor LM93 and compatibles"
+	depends on HWMON && I2C
+	select HWMON_VID
+	help
+	  If you say yes here you get support for National Semiconductor LM93
+	  sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called lm93.
+
 config SENSORS_MAX1619
 	tristate "Maxim MAX1619 sensor chip"
 	depends on I2C
@@ -406,8 +432,6 @@ config SENSORS_MAX6650
 
 config SENSORS_PC87360
 	tristate "National Semiconductor PC87360 family"
-	depends on I2C && EXPERIMENTAL
-	select I2C_ISA
 	select HWMON_VID
 	help
 	  If you say yes here you get access to the hardware monitoring
@@ -434,8 +458,7 @@ config SENSORS_PC87427
 
 config SENSORS_SIS5595
 	tristate "Silicon Integrated Systems Corp. SiS5595"
-	depends on I2C && PCI && EXPERIMENTAL
-	select I2C_ISA
+	depends on PCI
 	help
 	  If you say yes here you get support for the integrated sensors in
 	  SiS5595 South Bridges.
@@ -443,6 +466,18 @@ config SENSORS_SIS5595
 	  This driver can also be built as a module.  If so, the module
 	  will be called sis5595.
 
+config SENSORS_DME1737
+	tristate "SMSC DME1737 and compatibles"
+	depends on I2C && EXPERIMENTAL
+	select HWMON_VID
+	help
+	  If you say yes here you get support for the hardware monitoring
+	  and fan control features of the SMSC DME1737 (and compatibles
+	  like the Asus A8000) Super-I/O chip.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called dme1737.
+
 config SENSORS_SMSC47M1
 	tristate "SMSC LPC47M10x and compatibles"
 	help
@@ -486,10 +521,19 @@ config SENSORS_SMSC47B397
 	  This driver can also be built as a module.  If so, the module
 	  will be called smsc47b397.
 
+config SENSORS_THMC50
+	tristate "Texas Instruments THMC50 / Analog Devices ADM1022"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for Texas Instruments THMC50
+	  sensor chips and clones: the Analog Devices ADM1022.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called thmc50.
+
 config SENSORS_VIA686A
 	tristate "VIA686A"
-	depends on I2C && PCI
-	select I2C_ISA
+	depends on PCI
 	help
 	  If you say yes here you get support for the integrated sensors in
 	  Via 686A/B South Bridges.
@@ -510,9 +554,8 @@ config SENSORS_VT1211
 
 config SENSORS_VT8231
 	tristate "VIA VT8231"
-	depends on I2C && PCI && EXPERIMENTAL
+	depends on PCI
 	select HWMON_VID
-	select I2C_ISA
 	help
 	  If you say yes here then you get support for the integrated sensors
 	  in the VIA VT8231 device.
@@ -585,17 +628,16 @@ config SENSORS_W83627HF
 	  will be called w83627hf.
 
 config SENSORS_W83627EHF
-	tristate "Winbond W83627EHF"
-	depends on I2C && EXPERIMENTAL
-	select I2C_ISA
+	tristate "Winbond W83627EHF/DHG"
+	select HWMON_VID
 	help
-	  If you say yes here you get preliminary support for the hardware
+	  If you say yes here you get support for the hardware
 	  monitoring functionality of the Winbond W83627EHF Super-I/O chip.
-	  Only fan and temperature inputs are supported at the moment, while
-	  the chip does much more than that.
 
 	  This driver also supports the W83627EHG, which is the lead-free
-	  version of the W83627EHF.
+	  version of the W83627EHF, and the W83627DHG, which is a similar
+	  chip suited for specific Intel processors that use PECI such as
+	  the Core 2 Duo.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called w83627ehf.
diff --git a/drivers/hwmon/Makefile b/drivers/hwmon/Makefile
index cfaf338919dd..d04f90031ebf 100644
--- a/drivers/hwmon/Makefile
+++ b/drivers/hwmon/Makefile
@@ -14,6 +14,7 @@ obj-$(CONFIG_SENSORS_W83781D)	+= w83781d.o
 obj-$(CONFIG_SENSORS_W83791D)	+= w83791d.o
 
 obj-$(CONFIG_SENSORS_ABITUGURU)	+= abituguru.o
+obj-$(CONFIG_SENSORS_ABITUGURU3)+= abituguru3.o
 obj-$(CONFIG_SENSORS_AD7418)	+= ad7418.o
 obj-$(CONFIG_SENSORS_ADM1021)	+= adm1021.o
 obj-$(CONFIG_SENSORS_ADM1025)	+= adm1025.o
@@ -25,6 +26,7 @@ obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
+obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
 obj-$(CONFIG_SENSORS_DS1621)	+= ds1621.o
 obj-$(CONFIG_SENSORS_F71805F)	+= f71805f.o
 obj-$(CONFIG_SENSORS_FSCHER)	+= fscher.o
@@ -45,6 +47,7 @@ obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_LM87)	+= lm87.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_LM92)	+= lm92.o
+obj-$(CONFIG_SENSORS_LM93)	+= lm93.o
 obj-$(CONFIG_SENSORS_MAX1619)	+= max1619.o
 obj-$(CONFIG_SENSORS_MAX6650)	+= max6650.o
 obj-$(CONFIG_SENSORS_PC87360)	+= pc87360.o
@@ -53,6 +56,7 @@ obj-$(CONFIG_SENSORS_SIS5595)	+= sis5595.o
 obj-$(CONFIG_SENSORS_SMSC47B397)+= smsc47b397.o
 obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
+obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
diff --git a/drivers/hwmon/abituguru.c b/drivers/hwmon/abituguru.c
index bede4d990ea6..2317f4bb9c92 100644
--- a/drivers/hwmon/abituguru.c
+++ b/drivers/hwmon/abituguru.c
@@ -16,9 +16,9 @@
     Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
 */
 /*
-    This driver supports the sensor part of the custom Abit uGuru chip found
-    on Abit uGuru motherboards. Note: because of lack of specs the CPU / RAM /
-    etc voltage & frequency control is not supported!
+    This driver supports the sensor part of the first and second revision of
+    the custom Abit uGuru chip found on Abit uGuru motherboards. Note: because
+    of lack of specs the CPU/RAM voltage & frequency control is not supported!
 */
 #include <linux/module.h>
 #include <linux/sched.h>
@@ -31,6 +31,7 @@
 #include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/dmi.h>
 #include <asm/io.h>
 
 /* Banks */
@@ -418,7 +419,7 @@ static int __devinit
 abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
 				   u8 sensor_addr)
 {
-	u8 val, buf[3];
+	u8 val, test_flag, buf[3];
 	int i, ret = -ENODEV; /* error is the most common used retval :| */
 
 	/* If overriden by the user return the user selected type */
@@ -436,7 +437,7 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
 		return -ENODEV;
 
 	/* Test val is sane / usable for sensor type detection. */
-	if ((val < 10u) || (val > 240u)) {
+	if ((val < 10u) || (val > 250u)) {
 		printk(KERN_WARNING ABIT_UGURU_NAME
 			": bank1-sensor: %d reading (%d) too close to limits, "
 			"unable to determine sensor type, skipping sensor\n",
@@ -449,10 +450,20 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
 
 	ABIT_UGURU_DEBUG(2, "testing bank1 sensor %d\n", (int)sensor_addr);
 	/* Volt sensor test, enable volt low alarm, set min value ridicously
-	   high. If its a volt sensor this should always give us an alarm. */
-	buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE;
-	buf[1] = 245;
-	buf[2] = 250;
+	   high, or vica versa if the reading is very high. If its a volt
+	   sensor this should always give us an alarm. */
+	if (val <= 240u) {
+		buf[0] = ABIT_UGURU_VOLT_LOW_ALARM_ENABLE;
+		buf[1] = 245;
+		buf[2] = 250;
+		test_flag = ABIT_UGURU_VOLT_LOW_ALARM_FLAG;
+	} else {
+		buf[0] = ABIT_UGURU_VOLT_HIGH_ALARM_ENABLE;
+		buf[1] = 5;
+		buf[2] = 10;
+		test_flag = ABIT_UGURU_VOLT_HIGH_ALARM_FLAG;
+	}
+
 	if (abituguru_write(data, ABIT_UGURU_SENSOR_BANK1 + 2, sensor_addr,
 			buf, 3) != 3)
 		goto abituguru_detect_bank1_sensor_type_exit;
@@ -469,13 +480,13 @@ abituguru_detect_bank1_sensor_type(struct abituguru_data *data,
 				sensor_addr, buf, 3,
 				ABIT_UGURU_MAX_RETRIES) != 3)
 			goto abituguru_detect_bank1_sensor_type_exit;
-		if (buf[0] & ABIT_UGURU_VOLT_LOW_ALARM_FLAG) {
+		if (buf[0] & test_flag) {
 			ABIT_UGURU_DEBUG(2, "  found volt sensor\n");
 			ret = ABIT_UGURU_IN_SENSOR;
 			goto abituguru_detect_bank1_sensor_type_exit;
 		} else
 			ABIT_UGURU_DEBUG(2, "  alarm raised during volt "
-				"sensor test, but volt low flag not set\n");
+				"sensor test, but volt range flag not set\n");
 	} else
 		ABIT_UGURU_DEBUG(2, "  alarm not raised during volt sensor "
 			"test\n");
@@ -1287,6 +1298,7 @@ abituguru_probe_error:
 	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
 		device_remove_file(&pdev->dev,
 			&abituguru_sysfs_attr[i].dev_attr);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 	return res;
 }
@@ -1296,13 +1308,13 @@ static int __devexit abituguru_remove(struct platform_device *pdev)
 	int i;
 	struct abituguru_data *data = platform_get_drvdata(pdev);
 
-	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
 	for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
 		device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
 	for (i = 0; i < ARRAY_SIZE(abituguru_sysfs_attr); i++)
 		device_remove_file(&pdev->dev,
 			&abituguru_sysfs_attr[i].dev_attr);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
@@ -1436,6 +1448,15 @@ static int __init abituguru_init(void)
 	int address, err;
 	struct resource res = { .flags = IORESOURCE_IO };
 
+#ifdef CONFIG_DMI
+	const char *board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
+
+	/* safety check, refuse to load on non Abit motherboards */
+	if (!force && (!board_vendor ||
+			strcmp(board_vendor, "http://www.abit.com.tw/")))
+		return -ENODEV;
+#endif
+
 	address = abituguru_detect();
 	if (address < 0)
 		return address;
diff --git a/drivers/hwmon/abituguru3.c b/drivers/hwmon/abituguru3.c
new file mode 100644
index 000000000000..cdd8b6dea16d
--- /dev/null
+++ b/drivers/hwmon/abituguru3.c
@@ -0,0 +1,1141 @@
+/*
+    abituguru3.c Copyright (c) 2006 Hans de Goede <j.w.r.degoede@hhs.nl>
+
+    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.
+*/
+/*
+    This driver supports the sensor part of revision 3 of the custom Abit uGuru
+    chip found on newer Abit uGuru motherboards. Note: because of lack of specs
+    only reading the sensors and their settings is supported.
+*/
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/jiffies.h>
+#include <linux/mutex.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+#include <linux/platform_device.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <asm/io.h>
+
+/* uGuru3 bank addresses */
+#define ABIT_UGURU3_SETTINGS_BANK		0x01
+#define ABIT_UGURU3_SENSORS_BANK		0x08
+#define ABIT_UGURU3_MISC_BANK			0x09
+#define ABIT_UGURU3_ALARMS_START		0x1E
+#define ABIT_UGURU3_SETTINGS_START		0x24
+#define ABIT_UGURU3_VALUES_START		0x80
+#define ABIT_UGURU3_BOARD_ID			0x0A
+/* uGuru3 sensor bank flags */			     /* Alarm if: */
+#define ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE	0x01 /*  temp over warn */
+#define ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE	0x02 /*  volt over max */
+#define ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE	0x04 /*  volt under min */
+#define ABIT_UGURU3_TEMP_HIGH_ALARM_FLAG	0x10 /* temp is over warn */
+#define ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG	0x20 /* volt is over max */
+#define ABIT_UGURU3_VOLT_LOW_ALARM_FLAG		0x40 /* volt is under min */
+#define ABIT_UGURU3_FAN_LOW_ALARM_ENABLE	0x01 /*   fan under min */
+#define ABIT_UGURU3_BEEP_ENABLE			0x08 /* beep if alarm */
+#define ABIT_UGURU3_SHUTDOWN_ENABLE		0x80 /* shutdown if alarm */
+/* sensor types */
+#define ABIT_UGURU3_IN_SENSOR			0
+#define ABIT_UGURU3_TEMP_SENSOR			1
+#define ABIT_UGURU3_FAN_SENSOR			2
+
+/* Timeouts / Retries, if these turn out to need a lot of fiddling we could
+   convert them to params. Determined by trial and error. I assume this is
+   cpu-speed independent, since the ISA-bus and not the CPU should be the
+   bottleneck. */
+#define ABIT_UGURU3_WAIT_TIMEOUT		250
+/* Normally the 0xAC at the end of synchronize() is reported after the
+   first read, but sometimes not and we need to poll */
+#define ABIT_UGURU3_SYNCHRONIZE_TIMEOUT		5
+/* utility macros */
+#define ABIT_UGURU3_NAME			"abituguru3"
+#define ABIT_UGURU3_DEBUG(format, arg...)	\
+	if (verbose)				\
+		printk(KERN_DEBUG ABIT_UGURU3_NAME ": "	format , ## arg)
+
+/* Macros to help calculate the sysfs_names array length */
+#define ABIT_UGURU3_MAX_NO_SENSORS 26
+/* sum of strlen +1 of: in??_input\0, in??_{min,max}\0, in??_{min,max}_alarm\0,
+   in??_{min,max}_alarm_enable\0, in??_beep\0, in??_shutdown\0, in??_label\0 */
+#define ABIT_UGURU3_IN_NAMES_LENGTH (11 + 2 * 9 + 2 * 15 + 2 * 22 + 10 + 14 + 11)
+/* sum of strlen +1 of: temp??_input\0, temp??_max\0, temp??_crit\0,
+   temp??_alarm\0, temp??_alarm_enable\0, temp??_beep\0, temp??_shutdown\0,
+   temp??_label\0 */
+#define ABIT_UGURU3_TEMP_NAMES_LENGTH (13 + 11 + 12 + 13 + 20 + 12 + 16 + 13)
+/* sum of strlen +1 of: fan??_input\0, fan??_min\0, fan??_alarm\0,
+   fan??_alarm_enable\0, fan??_beep\0, fan??_shutdown\0, fan??_label\0 */
+#define ABIT_UGURU3_FAN_NAMES_LENGTH (12 + 10 + 12 + 19 + 11 + 15 + 12)
+/* Worst case scenario 16 in sensors (longest names_length) and the rest
+   temp sensors (second longest names_length). */
+#define ABIT_UGURU3_SYSFS_NAMES_LENGTH (16 * ABIT_UGURU3_IN_NAMES_LENGTH + \
+	(ABIT_UGURU3_MAX_NO_SENSORS - 16) * ABIT_UGURU3_TEMP_NAMES_LENGTH)
+
+/* All the macros below are named identical to the openguru2 program
+   reverse engineered by Louis Kruger, hence the names might not be 100%
+   logical. I could come up with better names, but I prefer keeping the names
+   identical so that this driver can be compared with his work more easily. */
+/* Two i/o-ports are used by uGuru */
+#define ABIT_UGURU3_BASE			0x00E0
+#define ABIT_UGURU3_CMD				0x00
+#define ABIT_UGURU3_DATA			0x04
+#define ABIT_UGURU3_REGION_LENGTH		5
+/* The wait_xxx functions return this on success and the last contents
+   of the DATA register (0-255) on failure. */
+#define ABIT_UGURU3_SUCCESS			-1
+/* uGuru status flags */
+#define ABIT_UGURU3_STATUS_READY_FOR_READ	0x01
+#define ABIT_UGURU3_STATUS_BUSY			0x02
+
+
+/* Structures */
+struct abituguru3_sensor_info {
+	const char* name;
+	int port;
+	int type;
+	int multiplier;
+	int divisor;
+	int offset;
+};
+
+struct abituguru3_motherboard_info {
+	u16 id;
+	const char *name;
+	/* + 1 -> end of sensors indicated by a sensor with name == NULL */
+	struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
+};
+
+/* For the Abit uGuru, we need to keep some data in memory.
+   The structure is dynamically allocated, at the same time when a new
+   abituguru3 device is allocated. */
+struct abituguru3_data {
+	struct class_device *class_dev; /* hwmon registered device */
+	struct mutex update_lock;	/* protect access to data and uGuru */
+	unsigned short addr;		/* uguru base address */
+	char valid;			/* !=0 if following fields are valid */
+	unsigned long last_updated;	/* In jiffies */
+
+	/* For convenience the sysfs attr and their names are generated
+	   automatically. We have max 10 entries per sensor (for in sensors) */
+	struct sensor_device_attribute_2 sysfs_attr[ABIT_UGURU3_MAX_NO_SENSORS
+		* 10];
+
+	/* Buffer to store the dynamically generated sysfs names */
+	char sysfs_names[ABIT_UGURU3_SYSFS_NAMES_LENGTH];
+
+	/* Pointer to the sensors info for the detected motherboard */
+	const struct abituguru3_sensor_info *sensors;
+
+	/* The abituguru3 supports upto 48 sensors, and thus has registers
+	   sets for 48 sensors, for convienence reasons / simplicity of the
+	   code we always read and store all registers for all 48 sensors */
+
+	/* Alarms for all 48 sensors (1 bit per sensor) */
+	u8 alarms[48/8];
+
+	/* Value of all 48 sensors */
+	u8 value[48];
+
+	/* Settings of all 48 sensors, note in and temp sensors (the first 32
+	   sensors) have 3 bytes of settings, while fans only have 2 bytes,
+	   for convenience we use 3 bytes for all sensors */
+	u8 settings[48][3];
+};
+
+
+/* Constants */
+static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
+	{ 0x000C, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS FAN",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x000D, "Abit AW8", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM1",		26, 1, 1, 1, 0 },
+		{ "PWM2",		27, 1, 1, 1, 0 },
+		{ "PWM3",		28, 1, 1, 1, 0 },
+		{ "PWM4",		29, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		36, 2, 60, 1, 0 },
+		{ "AUX3 Fan",		37, 2, 60, 1, 0 },
+		{ "AUX4 Fan",		38, 2, 60, 1, 0 },
+		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x000E, "AL-8", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x000F, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0010, "Abit NI8 SLI GR", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "NB 1.4V",		 4, 0, 10, 1, 0 },
+		{ "SB 1.5V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "SYS",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
+		{ "OTES1 Fan",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0011, "Abit AT8 32X", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 20, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V",	 6, 0, 20, 1, 0 },
+		{ "NB 1.8V",		 4, 0, 10, 1, 0 },
+		{ "NB 1.8V Dual",	 5, 0, 10, 1, 0 },
+		{ "HTV 1.2",		 3, 0, 10, 1, 0 },
+		{ "PCIE 1.2V",		12, 0, 10, 1, 0 },
+		{ "NB 1.2V",		13, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "NB",			25, 1, 1, 1, 0 },
+		{ "System",		26, 1, 1, 1, 0 },
+		{ "PWM",		27, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0012, "Abit AN8 32X", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 20, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "HyperTransport",	 3, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V",	 5, 0, 20, 1, 0 },
+		{ "NB",			 4, 0, 10, 1, 0 },
+		{ "SB",			 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "SYS",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0013, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM1",		26, 1, 1, 1, 0 },
+		{ "PWM2",		27, 1, 1, 1, 0 },
+		{ "PWM3",		28, 1, 1, 1, 0 },
+		{ "PWM4",		29, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		36, 2, 60, 1, 0 },
+		{ "AUX3 Fan",		37, 2, 60, 1, 0 },
+		{ "AUX4 Fan",		38, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0014, "Abit AB9 Pro", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 10, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0015, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR",		 1, 0, 20, 1, 0 },
+		{ "DDR VTT",		 2, 0, 10, 1, 0 },
+		{ "HyperTransport",	 3, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V",	 5, 0, 20, 1, 0 },
+		{ "NB",			 4, 0, 10, 1, 0 },
+		{ "SB",			 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "SYS",		25, 1, 1, 1, 0 },
+		{ "PWM",		26, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		33, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0016, "AW9D-MAX", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR2",		 1, 0, 20, 1, 0 },
+		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH & PCIE 1.5V",	 4, 0, 10, 1, 0 },
+		{ "MCH 2.5V",		 5, 0, 20, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM1",		26, 1, 1, 1, 0 },
+		{ "PWM2",		27, 1, 1, 1, 0 },
+		{ "PWM3",		28, 1, 1, 1, 0 },
+		{ "PWM4",		29, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "NB Fan",		33, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		36, 2, 60, 1, 0 },
+		{ "AUX3 Fan",		37, 2, 60, 1, 0 },
+		{ "OTES1 Fan",		38, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0017, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR2",		 1, 0, 20, 1, 0 },
+		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
+		{ "HyperTransport",	 3, 0, 10, 1, 0 },
+		{ "CPU VDDA 2.5V",	 6, 0, 20, 1, 0 },
+		{ "NB 1.8V",		 4, 0, 10, 1, 0 },
+		{ "NB 1.2V ",		13, 0, 10, 1, 0 },
+		{ "SB 1.2V",		 5, 0, 10, 1, 0 },
+		{ "PCIE 1.2V",		12, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "ATX +3.3V",		10, 0, 20, 1, 0 },
+		{ "ATX 5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		26, 1, 1, 1, 0 },
+		{ "PWM",		27, 1, 1, 1, 0 },
+		{ "CPU FAN",		32, 2, 60, 1, 0 },
+		{ "SYS FAN",		34, 2, 60, 1, 0 },
+		{ "AUX1 FAN",		35, 2, 60, 1, 0 },
+		{ "AUX2 FAN",		36, 2, 60, 1, 0 },
+		{ "AUX3 FAN",		37, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0018, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR2",		 1, 0, 20, 1, 0 },
+		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT",		 3, 0, 10, 1, 0 },
+		{ "MCH 1.25V",		 4, 0, 10, 1, 0 },
+		{ "ICHIO 1.5V",		 5, 0, 10, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM Phase1",		26, 1, 1, 1, 0 },
+		{ "PWM Phase2",		27, 1, 1, 1, 0 },
+		{ "PWM Phase3",		28, 1, 1, 1, 0 },
+		{ "PWM Phase4",		29, 1, 1, 1, 0 },
+		{ "PWM Phase5",		30, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		33, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0019, "unknown", {
+		{ "CPU Core",		 7, 0, 10, 1, 0 },
+		{ "DDR2",		13, 0, 20, 1, 0 },
+		{ "DDR2 VTT",		14, 0, 10, 1, 0 },
+		{ "CPU VTT",		 3, 0, 20, 1, 0 },
+		{ "NB 1.2V ",		 4, 0, 10, 1, 0 },
+		{ "SB 1.5V",		 6, 0, 10, 1, 0 },
+		{ "HyperTransport",	 5, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	12, 0, 60, 1, 0 },
+		{ "ATX +12V (4-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "ATX +3.3V",		10, 0, 20, 1, 0 },
+		{ "ATX 5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM Phase1",		26, 1, 1, 1, 0 },
+		{ "PWM Phase2",		27, 1, 1, 1, 0 },
+		{ "PWM Phase3",		28, 1, 1, 1, 0 },
+		{ "PWM Phase4",		29, 1, 1, 1, 0 },
+		{ "PWM Phase5",		30, 1, 1, 1, 0 },
+		{ "CPU FAN",		32, 2, 60, 1, 0 },
+		{ "SYS FAN",		34, 2, 60, 1, 0 },
+		{ "AUX1 FAN",		33, 2, 60, 1, 0 },
+		{ "AUX2 FAN",		35, 2, 60, 1, 0 },
+		{ "AUX3 FAN",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x001A, "unknown", {
+		{ "CPU Core",		 0, 0, 10, 1, 0 },
+		{ "DDR2",		 1, 0, 20, 1, 0 },
+		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
+		{ "CPU VTT 1.2V",	 3, 0, 10, 1, 0 },
+		{ "MCH 1.25V",		 4, 0, 10, 1, 0 },
+		{ "ICHIO 1.5V",		 5, 0, 10, 1, 0 },
+		{ "ICH 1.05V",		 6, 0, 10, 1, 0 },
+		{ "ATX +12V (24-Pin)",	 7, 0, 60, 1, 0 },
+		{ "ATX +12V (8-pin)",	 8, 0, 60, 1, 0 },
+		{ "ATX +5V",		 9, 0, 30, 1, 0 },
+		{ "+3.3V",		10, 0, 20, 1, 0 },
+		{ "5VSB",		11, 0, 30, 1, 0 },
+		{ "CPU",		24, 1, 1, 1, 0 },
+		{ "System ",		25, 1, 1, 1, 0 },
+		{ "PWM ",		26, 1, 1, 1, 0 },
+		{ "PWM Phase2",		27, 1, 1, 1, 0 },
+		{ "PWM Phase3",		28, 1, 1, 1, 0 },
+		{ "PWM Phase4",		29, 1, 1, 1, 0 },
+		{ "PWM Phase5",		30, 1, 1, 1, 0 },
+		{ "CPU Fan",		32, 2, 60, 1, 0 },
+		{ "SYS Fan",		34, 2, 60, 1, 0 },
+		{ "AUX1 Fan",		33, 2, 60, 1, 0 },
+		{ "AUX2 Fan",		35, 2, 60, 1, 0 },
+		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
+		{ NULL, 0, 0, 0, 0, 0 } }
+	},
+	{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
+};
+
+
+/* Insmod parameters */
+static int force;
+module_param(force, bool, 0);
+MODULE_PARM_DESC(force, "Set to one to force detection.");
+/* Default verbose is 1, since this driver is still in the testing phase */
+static int verbose = 1;
+module_param(verbose, bool, 0644);
+MODULE_PARM_DESC(verbose, "Enable/disable verbose error reporting");
+
+
+/* wait while the uguru is busy (usually after a write) */
+static int abituguru3_wait_while_busy(struct abituguru3_data *data)
+{
+	u8 x;
+	int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
+
+	while ((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
+			ABIT_UGURU3_STATUS_BUSY) {
+		timeout--;
+		if (timeout == 0)
+			return x;
+		/* sleep a bit before our last try, to give the uGuru3 one
+		   last chance to respond. */
+		if (timeout == 1)
+			msleep(1);
+	}
+	return ABIT_UGURU3_SUCCESS;
+}
+
+/* wait till uguru is ready to be read */
+static int abituguru3_wait_for_read(struct abituguru3_data *data)
+{
+	u8 x;
+	int timeout = ABIT_UGURU3_WAIT_TIMEOUT;
+
+	while (!((x = inb_p(data->addr + ABIT_UGURU3_DATA)) &
+			ABIT_UGURU3_STATUS_READY_FOR_READ)) {
+		timeout--;
+		if (timeout == 0)
+			return x;
+		/* sleep a bit before our last try, to give the uGuru3 one
+		   last chance to respond. */
+		if (timeout == 1)
+			msleep(1);
+	}
+	return ABIT_UGURU3_SUCCESS;
+}
+
+/* This synchronizes us with the uGuru3's protocol state machine, this
+   must be done before each command. */
+static int abituguru3_synchronize(struct abituguru3_data *data)
+{
+	int x, timeout = ABIT_UGURU3_SYNCHRONIZE_TIMEOUT;
+
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("synchronize timeout during initial busy "
+			"wait, status: 0x%02x\n", x);
+		return -EIO;
+	}
+
+	outb(0x20, data->addr + ABIT_UGURU3_DATA);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x20, "
+			"status: 0x%02x\n", x);
+		return -EIO;
+	}
+
+	outb(0x10, data->addr + ABIT_UGURU3_CMD);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x10, "
+			"status: 0x%02x\n", x);
+		return -EIO;
+	}
+
+	outb(0x00, data->addr + ABIT_UGURU3_CMD);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("synchronize timeout after sending 0x00, "
+			"status: 0x%02x\n", x);
+		return -EIO;
+	}
+
+	if ((x = abituguru3_wait_for_read(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("synchronize timeout waiting for read, "
+			"status: 0x%02x\n", x);
+		return -EIO;
+	}
+
+	while ((x = inb(data->addr + ABIT_UGURU3_CMD)) != 0xAC) {
+		timeout--;
+		if (timeout == 0) {
+			ABIT_UGURU3_DEBUG("synchronize timeout cmd does not "
+				"hold 0xAC after synchronize, cmd: 0x%02x\n",
+				x);
+			return -EIO;
+		}
+		msleep(1);
+	}
+	return 0;
+}
+
+/* Read count bytes from sensor sensor_addr in bank bank_addr and store the
+   result in buf */
+static int abituguru3_read(struct abituguru3_data *data, u8 bank, u8 offset,
+	u8 count, u8 *buf)
+{
+	int i, x;
+
+	if ((x = abituguru3_synchronize(data)))
+		return x;
+
+	outb(0x1A, data->addr + ABIT_UGURU3_DATA);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
+			"sending 0x1A, status: 0x%02x\n", (unsigned int)bank,
+			(unsigned int)offset, x);
+		return -EIO;
+	}
+
+	outb(bank, data->addr + ABIT_UGURU3_CMD);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
+			"sending the bank, status: 0x%02x\n",
+			(unsigned int)bank, (unsigned int)offset, x);
+		return -EIO;
+	}
+
+	outb(offset, data->addr + ABIT_UGURU3_CMD);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
+			"sending the offset, status: 0x%02x\n",
+			(unsigned int)bank, (unsigned int)offset, x);
+		return -EIO;
+	}
+
+	outb(count, data->addr + ABIT_UGURU3_CMD);
+	if ((x = abituguru3_wait_while_busy(data)) != ABIT_UGURU3_SUCCESS) {
+		ABIT_UGURU3_DEBUG("read from 0x%02x:0x%02x timed out after "
+			"sending the count, status: 0x%02x\n",
+			(unsigned int)bank, (unsigned int)offset, x);
+		return -EIO;
+	}
+
+	for (i = 0; i < count; i++) {
+		if ((x = abituguru3_wait_for_read(data)) !=
+				ABIT_UGURU3_SUCCESS) {
+			ABIT_UGURU3_DEBUG("timeout reading byte %d from "
+				"0x%02x:0x%02x, status: 0x%02x\n", i,
+				(unsigned int)bank, (unsigned int)offset, x);
+			break;
+		}
+		buf[i] = inb(data->addr + ABIT_UGURU3_CMD);
+	}
+	return i;
+}
+
+/* Sensor settings are stored 1 byte per offset with the bytes
+   placed add consecutive offsets. */
+static int abituguru3_read_increment_offset(struct abituguru3_data *data,
+					    u8 bank, u8 offset, u8 count,
+					    u8 *buf, int offset_count)
+{
+	int i, x;
+
+	for (i = 0; i < offset_count; i++)
+		if ((x = abituguru3_read(data, bank, offset + i, count,
+				buf + i * count)) != count)
+			return i * count + (i && (x < 0)) ? 0 : x;
+
+	return i * count;
+}
+
+/* Following are the sysfs callback functions. These functions expect:
+   sensor_device_attribute_2->index:   index into the data->sensors array
+   sensor_device_attribute_2->nr:      register offset, bitmask or NA. */
+static struct abituguru3_data *abituguru3_update_device(struct device *dev);
+
+static ssize_t show_value(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int value;
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru3_data *data = abituguru3_update_device(dev);
+	const struct abituguru3_sensor_info *sensor;
+
+	if (!data)
+		return -EIO;
+
+	sensor = &data->sensors[attr->index];
+
+	/* are we reading a setting, or is this a normal read? */
+	if (attr->nr)
+		value = data->settings[sensor->port][attr->nr];
+	else
+		value = data->value[sensor->port];
+
+	/* convert the value */
+	value = (value * sensor->multiplier) / sensor->divisor +
+		sensor->offset;
+
+	/* alternatively we could update the sensors settings struct for this,
+	   but then its contents would differ from the windows sw ini files */
+	if (sensor->type == ABIT_UGURU3_TEMP_SENSOR)
+		value *= 1000;
+
+	return sprintf(buf, "%d\n", value);
+}
+
+static ssize_t show_alarm(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	int port;
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru3_data *data = abituguru3_update_device(dev);
+
+	if (!data)
+		return -EIO;
+
+	port = data->sensors[attr->index].port;
+
+	/* See if the alarm bit for this sensor is set and if a bitmask is
+	   given in attr->nr also check if the alarm matches the type of alarm
+	   we're looking for (for volt it can be either low or high). The type
+	   is stored in a few readonly bits in the settings of the sensor. */
+	if ((data->alarms[port / 8] & (0x01 << (port % 8))) &&
+			(!attr->nr || (data->settings[port][0] & attr->nr)))
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t show_mask(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru3_data *data = dev_get_drvdata(dev);
+
+	if (data->settings[data->sensors[attr->index].port][0] & attr->nr)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static ssize_t show_label(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	struct abituguru3_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->sensors[attr->index].name);
+}
+
+static ssize_t show_name(struct device *dev,
+	struct device_attribute *devattr, char *buf)
+{
+	return sprintf(buf, "%s\n", ABIT_UGURU3_NAME);
+}
+
+/* Sysfs attr templates, the real entries are generated automatically. */
+static const
+struct sensor_device_attribute_2 abituguru3_sysfs_templ[3][10] = { {
+	SENSOR_ATTR_2(in%d_input, 0444, show_value, NULL, 0, 0),
+	SENSOR_ATTR_2(in%d_min, 0444, show_value, NULL, 1, 0),
+	SENSOR_ATTR_2(in%d_max, 0444, show_value, NULL, 2, 0),
+	SENSOR_ATTR_2(in%d_min_alarm, 0444, show_alarm, NULL,
+		ABIT_UGURU3_VOLT_LOW_ALARM_FLAG, 0),
+	SENSOR_ATTR_2(in%d_max_alarm, 0444, show_alarm, NULL,
+		ABIT_UGURU3_VOLT_HIGH_ALARM_FLAG, 0),
+	SENSOR_ATTR_2(in%d_beep, 0444, show_mask, NULL,
+		ABIT_UGURU3_BEEP_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_shutdown, 0444, show_mask, NULL,
+		ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_min_alarm_enable, 0444, show_mask, NULL,
+		ABIT_UGURU3_VOLT_LOW_ALARM_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_max_alarm_enable, 0444, show_mask, NULL,
+		ABIT_UGURU3_VOLT_HIGH_ALARM_ENABLE, 0),
+	SENSOR_ATTR_2(in%d_label, 0444, show_label, NULL, 0, 0)
+	}, {
+	SENSOR_ATTR_2(temp%d_input, 0444, show_value, NULL, 0, 0),
+	SENSOR_ATTR_2(temp%d_max, 0444, show_value, NULL, 1, 0),
+	SENSOR_ATTR_2(temp%d_crit, 0444, show_value, NULL, 2, 0),
+	SENSOR_ATTR_2(temp%d_alarm, 0444, show_alarm, NULL, 0, 0),
+	SENSOR_ATTR_2(temp%d_beep, 0444, show_mask, NULL,
+		ABIT_UGURU3_BEEP_ENABLE, 0),
+	SENSOR_ATTR_2(temp%d_shutdown, 0444, show_mask, NULL,
+		ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
+	SENSOR_ATTR_2(temp%d_alarm_enable, 0444, show_mask, NULL,
+		ABIT_UGURU3_TEMP_HIGH_ALARM_ENABLE, 0),
+	SENSOR_ATTR_2(temp%d_label, 0444, show_label, NULL, 0, 0)
+	}, {
+	SENSOR_ATTR_2(fan%d_input, 0444, show_value, NULL, 0, 0),
+	SENSOR_ATTR_2(fan%d_min, 0444, show_value, NULL, 1, 0),
+	SENSOR_ATTR_2(fan%d_alarm, 0444, show_alarm, NULL, 0, 0),
+	SENSOR_ATTR_2(fan%d_beep, 0444, show_mask, NULL,
+		ABIT_UGURU3_BEEP_ENABLE, 0),
+	SENSOR_ATTR_2(fan%d_shutdown, 0444, show_mask, NULL,
+		ABIT_UGURU3_SHUTDOWN_ENABLE, 0),
+	SENSOR_ATTR_2(fan%d_alarm_enable, 0444, show_mask, NULL,
+		ABIT_UGURU3_FAN_LOW_ALARM_ENABLE, 0),
+	SENSOR_ATTR_2(fan%d_label, 0444, show_label, NULL, 0, 0)
+} };
+
+static struct sensor_device_attribute_2 abituguru3_sysfs_attr[] = {
+	SENSOR_ATTR_2(name, 0444, show_name, NULL, 0, 0),
+};
+
+static int __devinit abituguru3_probe(struct platform_device *pdev)
+{
+	const int no_sysfs_attr[3] = { 10, 8, 7 };
+	int sensor_index[3] = { 0, 1, 1 };
+	struct abituguru3_data *data;
+	int i, j, type, used, sysfs_names_free, sysfs_attr_i, res = -ENODEV;
+	char *sysfs_filename;
+	u8 buf[2];
+	u16 id;
+
+	if (!(data = kzalloc(sizeof(struct abituguru3_data), GFP_KERNEL)))
+		return -ENOMEM;
+
+	data->addr = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
+	mutex_init(&data->update_lock);
+	platform_set_drvdata(pdev, data);
+
+	/* Read the motherboard ID */
+	if ((i = abituguru3_read(data, ABIT_UGURU3_MISC_BANK,
+			ABIT_UGURU3_BOARD_ID, 2, buf)) != 2) {
+		goto abituguru3_probe_error;
+	}
+
+	/* Completely read the uGuru to see if one really is there */
+	if (!abituguru3_update_device(&pdev->dev))
+		goto abituguru3_probe_error;
+
+	/* lookup the ID in our motherboard table */
+	id = ((u16)buf[0] << 8) | (u16)buf[1];
+	for (i = 0; abituguru3_motherboards[i].id; i++)
+		if (abituguru3_motherboards[i].id == id)
+			break;
+	if (!abituguru3_motherboards[i].id) {
+		printk(KERN_ERR ABIT_UGURU3_NAME ": error unknown motherboard "
+			"ID: %04X. Please report this to the abituguru3 "
+			"maintainer (see MAINTAINERS)\n", (unsigned int)id);
+		goto abituguru3_probe_error;
+	}
+	data->sensors = abituguru3_motherboards[i].sensors;
+	printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
+		"ID: %04X (%s)\n", (unsigned int)id,
+		abituguru3_motherboards[i].name);
+
+	/* Fill the sysfs attr array */
+	sysfs_attr_i = 0;
+	sysfs_filename = data->sysfs_names;
+	sysfs_names_free = ABIT_UGURU3_SYSFS_NAMES_LENGTH;
+	for (i = 0; data->sensors[i].name; i++) {
+		/* Fail safe check, this should never happen! */
+		if (i >= ABIT_UGURU3_MAX_NO_SENSORS) {
+			printk(KERN_ERR ABIT_UGURU3_NAME
+				": Fatal error motherboard has more sensors "
+				"then ABIT_UGURU3_MAX_NO_SENSORS. This should "
+				"never happen please report to the abituguru3 "
+				"maintainer (see MAINTAINERS)\n");
+			res = -ENAMETOOLONG;
+			goto abituguru3_probe_error;
+		}
+		type = data->sensors[i].type;
+		for (j = 0; j < no_sysfs_attr[type]; j++) {
+			used = snprintf(sysfs_filename, sysfs_names_free,
+				abituguru3_sysfs_templ[type][j].dev_attr.attr.
+				name, sensor_index[type]) + 1;
+			data->sysfs_attr[sysfs_attr_i] =
+				abituguru3_sysfs_templ[type][j];
+			data->sysfs_attr[sysfs_attr_i].dev_attr.attr.name =
+				sysfs_filename;
+			data->sysfs_attr[sysfs_attr_i].index = i;
+			sysfs_filename += used;
+			sysfs_names_free -= used;
+			sysfs_attr_i++;
+		}
+		sensor_index[type]++;
+	}
+	/* Fail safe check, this should never happen! */
+	if (sysfs_names_free < 0) {
+		printk(KERN_ERR ABIT_UGURU3_NAME
+			": Fatal error ran out of space for sysfs attr names. "
+			"This should never happen please report to the "
+			"abituguru3 maintainer (see MAINTAINERS)\n");
+		res = -ENAMETOOLONG;
+		goto abituguru3_probe_error;
+	}
+
+	/* Register sysfs hooks */
+	for (i = 0; i < sysfs_attr_i; i++)
+		if (device_create_file(&pdev->dev,
+				&data->sysfs_attr[i].dev_attr))
+			goto abituguru3_probe_error;
+	for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
+		if (device_create_file(&pdev->dev,
+				&abituguru3_sysfs_attr[i].dev_attr))
+			goto abituguru3_probe_error;
+
+	data->class_dev = hwmon_device_register(&pdev->dev);
+	if (IS_ERR(data->class_dev)) {
+		res = PTR_ERR(data->class_dev);
+		goto abituguru3_probe_error;
+	}
+
+	return 0; /* success */
+
+abituguru3_probe_error:
+	for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
+		device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
+		device_remove_file(&pdev->dev,
+			&abituguru3_sysfs_attr[i].dev_attr);
+	kfree(data);
+	return res;
+}
+
+static int __devexit abituguru3_remove(struct platform_device *pdev)
+{
+	int i;
+	struct abituguru3_data *data = platform_get_drvdata(pdev);
+
+	platform_set_drvdata(pdev, NULL);
+	hwmon_device_unregister(data->class_dev);
+	for (i = 0; data->sysfs_attr[i].dev_attr.attr.name; i++)
+		device_remove_file(&pdev->dev, &data->sysfs_attr[i].dev_attr);
+	for (i = 0; i < ARRAY_SIZE(abituguru3_sysfs_attr); i++)
+		device_remove_file(&pdev->dev,
+			&abituguru3_sysfs_attr[i].dev_attr);
+	kfree(data);
+
+	return 0;
+}
+
+static struct abituguru3_data *abituguru3_update_device(struct device *dev)
+{
+	int i;
+	struct abituguru3_data *data = dev_get_drvdata(dev);
+
+	mutex_lock(&data->update_lock);
+	if (!data->valid || time_after(jiffies, data->last_updated + HZ)) {
+		/* Clear data->valid while updating */
+		data->valid = 0;
+		/* Read alarms */
+		if (abituguru3_read_increment_offset(data,
+				ABIT_UGURU3_SETTINGS_BANK,
+				ABIT_UGURU3_ALARMS_START,
+				1, data->alarms, 48/8) != (48/8))
+			goto LEAVE_UPDATE;
+		/* Read in and temp sensors (3 byte settings / sensor) */
+		for (i = 0; i < 32; i++) {
+			if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
+					ABIT_UGURU3_VALUES_START + i,
+					1, &data->value[i]) != 1)
+				goto LEAVE_UPDATE;
+			if (abituguru3_read_increment_offset(data,
+					ABIT_UGURU3_SETTINGS_BANK,
+					ABIT_UGURU3_SETTINGS_START + i * 3,
+					1,
+					data->settings[i], 3) != 3)
+				goto LEAVE_UPDATE;
+		}
+		/* Read temp sensors (2 byte settings / sensor) */
+		for (i = 0; i < 16; i++) {
+			if (abituguru3_read(data, ABIT_UGURU3_SENSORS_BANK,
+					ABIT_UGURU3_VALUES_START + 32 + i,
+					1, &data->value[32 + i]) != 1)
+				goto LEAVE_UPDATE;
+			if (abituguru3_read_increment_offset(data,
+					ABIT_UGURU3_SETTINGS_BANK,
+					ABIT_UGURU3_SETTINGS_START + 32 * 3 +
+						i * 2, 1,
+					data->settings[32 + i], 2) != 2)
+				goto LEAVE_UPDATE;
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+LEAVE_UPDATE:
+	mutex_unlock(&data->update_lock);
+	if (data->valid)
+		return data;
+	else
+		return NULL;
+}
+
+#ifdef CONFIG_PM
+static int abituguru3_suspend(struct platform_device *pdev, pm_message_t state)
+{
+	struct abituguru3_data *data = platform_get_drvdata(pdev);
+	/* make sure all communications with the uguru3 are done and no new
+	   ones are started */
+	mutex_lock(&data->update_lock);
+	return 0;
+}
+
+static int abituguru3_resume(struct platform_device *pdev)
+{
+	struct abituguru3_data *data = platform_get_drvdata(pdev);
+	mutex_unlock(&data->update_lock);
+	return 0;
+}
+#else
+#define abituguru3_suspend	NULL
+#define abituguru3_resume	NULL
+#endif /* CONFIG_PM */
+
+static struct platform_driver abituguru3_driver = {
+	.driver = {
+		.owner	= THIS_MODULE,
+		.name	= ABIT_UGURU3_NAME,
+	},
+	.probe	= abituguru3_probe,
+	.remove	= __devexit_p(abituguru3_remove),
+	.suspend = abituguru3_suspend,
+	.resume = abituguru3_resume
+};
+
+static int __init abituguru3_detect(void)
+{
+	/* See if there is an uguru3 there. An idle uGuru3 will hold 0x00 or
+	   0x08 at DATA and 0xAC at CMD. Sometimes the uGuru3 will hold 0x05
+	   at CMD instead, why is unknown. So we test for 0x05 too. */
+	u8 data_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_DATA);
+	u8 cmd_val = inb_p(ABIT_UGURU3_BASE + ABIT_UGURU3_CMD);
+	if (((data_val == 0x00) || (data_val == 0x08)) &&
+			((cmd_val == 0xAC) || (cmd_val == 0x05)))
+		return ABIT_UGURU3_BASE;
+
+	ABIT_UGURU3_DEBUG("no Abit uGuru3 found, data = 0x%02X, cmd = "
+		"0x%02X\n", (unsigned int)data_val, (unsigned int)cmd_val);
+
+	if (force) {
+		printk(KERN_INFO ABIT_UGURU3_NAME ": Assuming Abit uGuru3 is "
+				"present because of \"force\" parameter\n");
+		return ABIT_UGURU3_BASE;
+	}
+
+	/* No uGuru3 found */
+	return -ENODEV;
+}
+
+static struct platform_device *abituguru3_pdev;
+
+static int __init abituguru3_init(void)
+{
+	int address, err;
+	struct resource res = { .flags = IORESOURCE_IO };
+
+	address = abituguru3_detect();
+	if (address < 0)
+		return address;
+
+	err = platform_driver_register(&abituguru3_driver);
+	if (err)
+		goto exit;
+
+	abituguru3_pdev = platform_device_alloc(ABIT_UGURU3_NAME, address);
+	if (!abituguru3_pdev) {
+		printk(KERN_ERR ABIT_UGURU3_NAME
+			": Device allocation failed\n");
+		err = -ENOMEM;
+		goto exit_driver_unregister;
+	}
+
+	res.start = address;
+	res.end = address + ABIT_UGURU3_REGION_LENGTH - 1;
+	res.name = ABIT_UGURU3_NAME;
+
+	err = platform_device_add_resources(abituguru3_pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR ABIT_UGURU3_NAME
+			": Device resource addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(abituguru3_pdev);
+	if (err) {
+		printk(KERN_ERR ABIT_UGURU3_NAME
+			": Device addition failed (%d)\n", err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(abituguru3_pdev);
+exit_driver_unregister:
+	platform_driver_unregister(&abituguru3_driver);
+exit:
+	return err;
+}
+
+static void __exit abituguru3_exit(void)
+{
+	platform_device_unregister(abituguru3_pdev);
+	platform_driver_unregister(&abituguru3_driver);
+}
+
+MODULE_AUTHOR("Hans de Goede <j.w.r.degoede@hhs.nl>");
+MODULE_DESCRIPTION("Abit uGuru3 Sensor device");
+MODULE_LICENSE("GPL");
+
+module_init(abituguru3_init);
+module_exit(abituguru3_exit);
diff --git a/drivers/hwmon/ams/ams-core.c b/drivers/hwmon/ams/ams-core.c
index 6db973739725..a112a03e8f29 100644
--- a/drivers/hwmon/ams/ams-core.c
+++ b/drivers/hwmon/ams/ams-core.c
@@ -23,7 +23,6 @@
 #include <linux/types.h>
 #include <linux/errno.h>
 #include <linux/init.h>
-#include <linux/module.h>
 #include <asm/pmac_pfunc.h>
 #include <asm/of_platform.h>
 
diff --git a/drivers/hwmon/applesmc.c b/drivers/hwmon/applesmc.c
index eb81a6430fe4..571f49e80277 100644
--- a/drivers/hwmon/applesmc.c
+++ b/drivers/hwmon/applesmc.c
@@ -79,11 +79,15 @@
 
 /*
  * Temperature sensors keys (sp78 - 2 bytes).
- * First set for Macbook(Pro), second for Macmini.
  */
 static const char* temperature_sensors_sets[][13] = {
+/* Set 0: Macbook Pro */
 	{ "TA0P", "TB0T", "TC0D", "TC0P", "TG0H", "TG0P", "TG0T", "Th0H",
 	  "Th1H", "Tm0P", "Ts0P", "Ts1P", NULL },
+/* Set 1: Macbook set */
+	{ "TB0T", "TC0D", "TC0P", "TM0P", "TN0P", "TN1P", "Th0H", "Th0S",
+	  "Th1H", "Ts0P", NULL },
+/* Set 2: Macmini set */
 	{ "TC0D", "TC0P", NULL }
 };
 
@@ -1048,7 +1052,7 @@ static const struct attribute_group temperature_attributes_group =
 /*
  * applesmc_dmi_match - found a match.  return one, short-circuiting the hunt.
  */
-static int applesmc_dmi_match(struct dmi_system_id *id)
+static int applesmc_dmi_match(const struct dmi_system_id *id)
 {
 	int i = 0;
 	struct dmi_match_data* dmi_data = id->driver_data;
@@ -1129,10 +1133,10 @@ static void applesmc_release_accelerometer(void)
 static __initdata struct dmi_match_data applesmc_dmi_data[] = {
 /* MacBook Pro: accelerometer, backlight and temperature set 0 */
 	{ .accelerometer = 1, .light = 1, .temperature_set = 0 },
-/* MacBook: accelerometer and temperature set 0 */
-	{ .accelerometer = 1, .light = 0, .temperature_set = 0 },
-/* MacBook: temperature set 1 */
-	{ .accelerometer = 0, .light = 0, .temperature_set = 1 }
+/* MacBook: accelerometer and temperature set 1 */
+	{ .accelerometer = 1, .light = 0, .temperature_set = 1 },
+/* MacMini: temperature set 2 */
+	{ .accelerometer = 0, .light = 0, .temperature_set = 2 },
 };
 
 /* Note that DMI_MATCH(...,"MacBook") will match "MacBookPro1,1".
diff --git a/drivers/hwmon/coretemp.c b/drivers/hwmon/coretemp.c
index 6d54c8caed79..7c1795225b06 100644
--- a/drivers/hwmon/coretemp.c
+++ b/drivers/hwmon/coretemp.c
@@ -318,7 +318,7 @@ exit:
 }
 
 #ifdef CONFIG_HOTPLUG_CPU
-void coretemp_device_remove(unsigned int cpu)
+static void coretemp_device_remove(unsigned int cpu)
 {
 	struct pdev_entry *p, *n;
 	mutex_lock(&pdev_list_mutex);
diff --git a/drivers/hwmon/dme1737.c b/drivers/hwmon/dme1737.c
new file mode 100644
index 000000000000..e9cbc727664d
--- /dev/null
+++ b/drivers/hwmon/dme1737.c
@@ -0,0 +1,2080 @@
+/*
+ * dme1737.c - driver for the SMSC DME1737 and Asus A8000 Super-I/O chips
+ *             integrated hardware monitoring features.
+ * Copyright (c) 2007 Juerg Haefliger <juergh@gmail.com>
+ *
+ * This driver is based on the LM85 driver. The hardware monitoring
+ * capabilities of the DME1737 are very similar to the LM85 with some
+ * additional features. Even though the DME1737 is a Super-I/O chip, the
+ * hardware monitoring registers are only accessible via SMBus.
+ *
+ * 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/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+#include <asm/io.h>
+
+/* Module load parameters */
+static int force_start;
+module_param(force_start, bool, 0);
+MODULE_PARM_DESC(force_start, "Force the chip to start monitoring inputs");
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = {0x2c, 0x2d, 0x2e, I2C_CLIENT_END};
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(dme1737);
+
+/* ---------------------------------------------------------------------
+ * Registers
+ *
+ * The sensors are defined as follows:
+ *
+ * Voltages                          Temperatures
+ * --------                          ------------
+ * in0   +5VTR (+5V stdby)           temp1   Remote diode 1
+ * in1   Vccp  (proc core)           temp2   Internal temp
+ * in2   VCC   (internal +3.3V)      temp3   Remote diode 2
+ * in3   +5V
+ * in4   +12V
+ * in5   VTR   (+3.3V stby)
+ * in6   Vbat
+ *
+ * --------------------------------------------------------------------- */
+
+/* Voltages (in) numbered 0-6 (ix) */
+#define	DME1737_REG_IN(ix)		((ix) < 5 ? 0x20 + (ix) \
+						  : 0x94 + (ix))
+#define	DME1737_REG_IN_MIN(ix)		((ix) < 5 ? 0x44 + (ix) * 2 \
+						  : 0x91 + (ix) * 2)
+#define	DME1737_REG_IN_MAX(ix)		((ix) < 5 ? 0x45 + (ix) * 2 \
+						  : 0x92 + (ix) * 2)
+
+/* Temperatures (temp) numbered 0-2 (ix) */
+#define DME1737_REG_TEMP(ix)		(0x25 + (ix))
+#define DME1737_REG_TEMP_MIN(ix)	(0x4e + (ix) * 2)
+#define DME1737_REG_TEMP_MAX(ix)	(0x4f + (ix) * 2)
+#define DME1737_REG_TEMP_OFFSET(ix)	((ix) == 0 ? 0x1f \
+						   : 0x1c + (ix))
+
+/* Voltage and temperature LSBs
+ * The LSBs (4 bits each) are stored in 5 registers with the following layouts:
+ *    IN_TEMP_LSB(0) = [in5, in6]
+ *    IN_TEMP_LSB(1) = [temp3, temp1]
+ *    IN_TEMP_LSB(2) = [in4, temp2]
+ *    IN_TEMP_LSB(3) = [in3, in0]
+ *    IN_TEMP_LSB(4) = [in2, in1] */
+#define DME1737_REG_IN_TEMP_LSB(ix)	(0x84 + (ix))
+static const u8 DME1737_REG_IN_LSB[] = {3, 4, 4, 3, 2, 0, 0};
+static const u8 DME1737_REG_IN_LSB_SHL[] = {4, 4, 0, 0, 0, 0, 4};
+static const u8 DME1737_REG_TEMP_LSB[] = {1, 2, 1};
+static const u8 DME1737_REG_TEMP_LSB_SHL[] = {4, 4, 0};
+
+/* Fans numbered 0-5 (ix) */
+#define DME1737_REG_FAN(ix)		((ix) < 4 ? 0x28 + (ix) * 2 \
+						  : 0xa1 + (ix) * 2)
+#define DME1737_REG_FAN_MIN(ix)		((ix) < 4 ? 0x54 + (ix) * 2 \
+						  : 0xa5 + (ix) * 2)
+#define DME1737_REG_FAN_OPT(ix)		((ix) < 4 ? 0x90 + (ix) \
+						  : 0xb2 + (ix))
+#define DME1737_REG_FAN_MAX(ix)		(0xb4 + (ix)) /* only for fan[4-5] */
+
+/* PWMs numbered 0-2, 4-5 (ix) */
+#define DME1737_REG_PWM(ix)		((ix) < 3 ? 0x30 + (ix) \
+						  : 0xa1 + (ix))
+#define DME1737_REG_PWM_CONFIG(ix)	(0x5c + (ix)) /* only for pwm[0-2] */
+#define DME1737_REG_PWM_MIN(ix)		(0x64 + (ix)) /* only for pwm[0-2] */
+#define DME1737_REG_PWM_FREQ(ix)	((ix) < 3 ? 0x5f + (ix) \
+						  : 0xa3 + (ix))
+/* The layout of the ramp rate registers is different from the other pwm
+ * registers. The bits for the 3 PWMs are stored in 2 registers:
+ *    PWM_RR(0) = [OFF3, OFF2,  OFF1,  RES,   RR1E, RR1-2, RR1-1, RR1-0]
+ *    PWM_RR(1) = [RR2E, RR2-2, RR2-1, RR2-0, RR3E, RR3-2, RR3-1, RR3-0] */
+#define DME1737_REG_PWM_RR(ix)		(0x62 + (ix)) /* only for pwm[0-2] */
+
+/* Thermal zones 0-2 */
+#define DME1737_REG_ZONE_LOW(ix)	(0x67 + (ix))
+#define DME1737_REG_ZONE_ABS(ix)	(0x6a + (ix))
+/* The layout of the hysteresis registers is different from the other zone
+ * registers. The bits for the 3 zones are stored in 2 registers:
+ *    ZONE_HYST(0) = [H1-3,  H1-2,  H1-1, H1-0, H2-3, H2-2, H2-1, H2-0]
+ *    ZONE_HYST(1) = [H3-3,  H3-2,  H3-1, H3-0, RES,  RES,  RES,  RES] */
+#define DME1737_REG_ZONE_HYST(ix)	(0x6d + (ix))
+
+/* Alarm registers and bit mapping
+ * The 3 8-bit alarm registers will be concatenated to a single 32-bit
+ * alarm value [0, ALARM3, ALARM2, ALARM1]. */
+#define DME1737_REG_ALARM1		0x41
+#define DME1737_REG_ALARM2		0x42
+#define DME1737_REG_ALARM3		0x83
+static const u8 DME1737_BIT_ALARM_IN[] = {0, 1, 2, 3, 8, 16, 17};
+static const u8 DME1737_BIT_ALARM_TEMP[] = {4, 5, 6};
+static const u8 DME1737_BIT_ALARM_FAN[] = {10, 11, 12, 13, 22, 23};
+
+/* Miscellaneous registers */
+#define DME1737_REG_COMPANY		0x3e
+#define DME1737_REG_VERSTEP		0x3f
+#define DME1737_REG_CONFIG		0x40
+#define DME1737_REG_CONFIG2		0x7f
+#define DME1737_REG_VID			0x43
+#define DME1737_REG_TACH_PWM		0x81
+
+/* ---------------------------------------------------------------------
+ * Misc defines
+ * --------------------------------------------------------------------- */
+
+/* Chip identification */
+#define DME1737_COMPANY_SMSC	0x5c
+#define DME1737_VERSTEP		0x88
+#define DME1737_VERSTEP_MASK	0xf8
+
+/* ---------------------------------------------------------------------
+ * Data structures and manipulation thereof
+ * --------------------------------------------------------------------- */
+
+struct dme1737_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+
+	struct mutex update_lock;
+	int valid;			/* !=0 if following fields are valid */
+	unsigned long last_update;	/* in jiffies */
+	unsigned long last_vbat;	/* in jiffies */
+
+	u8 vid;
+	u8 pwm_rr_en;
+	u8 has_pwm;
+	u8 has_fan;
+
+	/* Register values */
+	u16 in[7];
+	u8  in_min[7];
+	u8  in_max[7];
+	s16 temp[3];
+	s8  temp_min[3];
+	s8  temp_max[3];
+	s8  temp_offset[3];
+	u8  config;
+	u8  config2;
+	u8  vrm;
+	u16 fan[6];
+	u16 fan_min[6];
+	u8  fan_max[2];
+	u8  fan_opt[6];
+	u8  pwm[6];
+	u8  pwm_min[3];
+	u8  pwm_config[3];
+	u8  pwm_acz[3];
+	u8  pwm_freq[6];
+	u8  pwm_rr[2];
+	u8  zone_low[3];
+	u8  zone_abs[3];
+	u8  zone_hyst[2];
+	u32 alarms;
+};
+
+/* Nominal voltage values */
+static const int IN_NOMINAL[] = {5000, 2250, 3300, 5000, 12000, 3300, 3300};
+
+/* Voltage input
+ * Voltage inputs have 16 bits resolution, limit values have 8 bits
+ * resolution. */
+static inline int IN_FROM_REG(int reg, int ix, int res)
+{
+	return (reg * IN_NOMINAL[ix] + (3 << (res - 3))) / (3 << (res - 2));
+}
+
+static inline int IN_TO_REG(int val, int ix)
+{
+	return SENSORS_LIMIT((val * 192 + IN_NOMINAL[ix] / 2) /
+			     IN_NOMINAL[ix], 0, 255);
+}
+
+/* Temperature input
+ * The register values represent temperatures in 2's complement notation from
+ * -127 degrees C to +127 degrees C. Temp inputs have 16 bits resolution, limit
+ * values have 8 bits resolution. */
+static inline int TEMP_FROM_REG(int reg, int res)
+{
+	return (reg * 1000) >> (res - 8);
+}
+
+static inline int TEMP_TO_REG(int val)
+{
+	return SENSORS_LIMIT((val < 0 ? val - 500 : val + 500) / 1000,
+			     -128, 127);
+}
+
+/* Temperature range */
+static const int TEMP_RANGE[] = {2000, 2500, 3333, 4000, 5000, 6666, 8000,
+				 10000, 13333, 16000, 20000, 26666, 32000,
+				 40000, 53333, 80000};
+
+static inline int TEMP_RANGE_FROM_REG(int reg)
+{
+	return TEMP_RANGE[(reg >> 4) & 0x0f];
+}
+
+static int TEMP_RANGE_TO_REG(int val, int reg)
+{
+	int i;
+
+	for (i = 15; i > 0; i--) {
+		if (val > (TEMP_RANGE[i] + TEMP_RANGE[i - 1] + 1) / 2) {
+			break;
+		}
+	}
+
+	return (reg & 0x0f) | (i << 4);
+}
+
+/* Temperature hysteresis
+ * Register layout:
+ *    reg[0] = [H1-3, H1-2, H1-1, H1-0, H2-3, H2-2, H2-1, H2-0]
+ *    reg[1] = [H3-3, H3-2, H3-1, H3-0, xxxx, xxxx, xxxx, xxxx] */
+static inline int TEMP_HYST_FROM_REG(int reg, int ix)
+{
+	return (((ix == 1) ? reg : reg >> 4) & 0x0f) * 1000;
+}
+
+static inline int TEMP_HYST_TO_REG(int val, int ix, int reg)
+{
+	int hyst = SENSORS_LIMIT((val + 500) / 1000, 0, 15);
+
+	return (ix == 1) ? (reg & 0xf0) | hyst : (reg & 0x0f) | (hyst << 4);
+}
+
+/* Fan input RPM */
+static inline int FAN_FROM_REG(int reg, int tpc)
+{
+	return (reg == 0 || reg == 0xffff) ? 0 :
+		(tpc == 0) ? 90000 * 60 / reg : tpc * reg;
+}
+
+static inline int FAN_TO_REG(int val, int tpc)
+{
+	return SENSORS_LIMIT((tpc == 0) ? 90000 * 60 / val : val / tpc,
+			     0, 0xffff);
+}
+
+/* Fan TPC (tach pulse count)
+ * Converts a register value to a TPC multiplier or returns 0 if the tachometer
+ * is configured in legacy (non-tpc) mode */
+static inline int FAN_TPC_FROM_REG(int reg)
+{
+	return (reg & 0x20) ? 0 : 60 >> (reg & 0x03);
+}
+
+/* Fan type
+ * The type of a fan is expressed in number of pulses-per-revolution that it
+ * emits */
+static inline int FAN_TYPE_FROM_REG(int reg)
+{
+	int edge = (reg >> 1) & 0x03;
+
+	return (edge > 0) ? 1 << (edge - 1) : 0;
+}
+
+static inline int FAN_TYPE_TO_REG(int val, int reg)
+{
+	int edge = (val == 4) ? 3 : val;
+
+	return (reg & 0xf9) | (edge << 1);
+}
+
+/* Fan max RPM */
+static const int FAN_MAX[] = {0x54, 0x38, 0x2a, 0x21, 0x1c, 0x18, 0x15, 0x12,
+			      0x11, 0x0f, 0x0e};
+
+static int FAN_MAX_FROM_REG(int reg)
+{
+	int i;
+
+	for (i = 10; i > 0; i--) {
+		if (reg == FAN_MAX[i]) {
+			break;
+		}
+	}
+
+	return 1000 + i * 500;
+}
+
+static int FAN_MAX_TO_REG(int val)
+{
+	int i;
+
+	for (i = 10; i > 0; i--) {
+		if (val > (1000 + (i - 1) * 500)) {
+			break;
+		}
+	}
+
+	return FAN_MAX[i];
+}
+
+/* PWM enable
+ * Register to enable mapping:
+ * 000:  2  fan on zone 1 auto
+ * 001:  2  fan on zone 2 auto
+ * 010:  2  fan on zone 3 auto
+ * 011:  0  fan full on
+ * 100: -1  fan disabled
+ * 101:  2  fan on hottest of zones 2,3 auto
+ * 110:  2  fan on hottest of zones 1,2,3 auto
+ * 111:  1  fan in manual mode */
+static inline int PWM_EN_FROM_REG(int reg)
+{
+	static const int en[] = {2, 2, 2, 0, -1, 2, 2, 1};
+
+	return en[(reg >> 5) & 0x07];
+}
+
+static inline int PWM_EN_TO_REG(int val, int reg)
+{
+	int en = (val == 1) ? 7 : 3;
+
+	return (reg & 0x1f) | ((en & 0x07) << 5);
+}
+
+/* PWM auto channels zone
+ * Register to auto channels zone mapping (ACZ is a bitfield with bit x
+ * corresponding to zone x+1):
+ * 000: 001  fan on zone 1 auto
+ * 001: 010  fan on zone 2 auto
+ * 010: 100  fan on zone 3 auto
+ * 011: 000  fan full on
+ * 100: 000  fan disabled
+ * 101: 110  fan on hottest of zones 2,3 auto
+ * 110: 111  fan on hottest of zones 1,2,3 auto
+ * 111: 000  fan in manual mode */
+static inline int PWM_ACZ_FROM_REG(int reg)
+{
+	static const int acz[] = {1, 2, 4, 0, 0, 6, 7, 0};
+
+	return acz[(reg >> 5) & 0x07];
+}
+
+static inline int PWM_ACZ_TO_REG(int val, int reg)
+{
+	int acz = (val == 4) ? 2 : val - 1;
+
+	return (reg & 0x1f) | ((acz & 0x07) << 5);
+}
+
+/* PWM frequency */
+static const int PWM_FREQ[] = {11, 15, 22, 29, 35, 44, 59, 88,
+			       15000, 20000, 30000, 25000, 0, 0, 0, 0};
+
+static inline int PWM_FREQ_FROM_REG(int reg)
+{
+	return PWM_FREQ[reg & 0x0f];
+}
+
+static int PWM_FREQ_TO_REG(int val, int reg)
+{
+	int i;
+
+	/* the first two cases are special - stupid chip design! */
+	if (val > 27500) {
+		i = 10;
+	} else if (val > 22500) {
+		i = 11;
+	} else {
+		for (i = 9; i > 0; i--) {
+			if (val > (PWM_FREQ[i] + PWM_FREQ[i - 1] + 1) / 2) {
+				break;
+			}
+		}
+	}
+
+	return (reg & 0xf0) | i;
+}
+
+/* PWM ramp rate
+ * Register layout:
+ *    reg[0] = [OFF3,  OFF2,  OFF1,  RES,   RR1-E, RR1-2, RR1-1, RR1-0]
+ *    reg[1] = [RR2-E, RR2-2, RR2-1, RR2-0, RR3-E, RR3-2, RR3-1, RR3-0] */
+static const u8 PWM_RR[] = {206, 104, 69, 41, 26, 18, 10, 5};
+
+static inline int PWM_RR_FROM_REG(int reg, int ix)
+{
+	int rr = (ix == 1) ? reg >> 4 : reg;
+
+	return (rr & 0x08) ? PWM_RR[rr & 0x07] : 0;
+}
+
+static int PWM_RR_TO_REG(int val, int ix, int reg)
+{
+	int i;
+
+	for (i = 0; i < 7; i++) {
+		if (val > (PWM_RR[i] + PWM_RR[i + 1] + 1) / 2) {
+			break;
+		}
+	}
+
+	return (ix == 1) ? (reg & 0x8f) | (i << 4) : (reg & 0xf8) | i;
+}
+
+/* PWM ramp rate enable */
+static inline int PWM_RR_EN_FROM_REG(int reg, int ix)
+{
+	return PWM_RR_FROM_REG(reg, ix) ? 1 : 0;
+}
+
+static inline int PWM_RR_EN_TO_REG(int val, int ix, int reg)
+{
+	int en = (ix == 1) ? 0x80 : 0x08;
+
+	return val ? reg | en : reg & ~en;
+}
+
+/* PWM min/off
+ * The PWM min/off bits are part of the PMW ramp rate register 0 (see above for
+ * the register layout). */
+static inline int PWM_OFF_FROM_REG(int reg, int ix)
+{
+	return (reg >> (ix + 5)) & 0x01;
+}
+
+static inline int PWM_OFF_TO_REG(int val, int ix, int reg)
+{
+	return (reg & ~(1 << (ix + 5))) | ((val & 0x01) << (ix + 5));
+}
+
+/* ---------------------------------------------------------------------
+ * Device I/O access
+ * --------------------------------------------------------------------- */
+
+static u8 dme1737_read(struct i2c_client *client, u8 reg)
+{
+	s32 val = i2c_smbus_read_byte_data(client, reg);
+
+	if (val < 0) {
+		dev_warn(&client->dev, "Read from register 0x%02x failed! "
+			 "Please report to the driver maintainer.\n", reg);
+	}
+
+	return val;
+}
+
+static s32 dme1737_write(struct i2c_client *client, u8 reg, u8 value)
+{
+	s32 res = i2c_smbus_write_byte_data(client, reg, value);
+
+	if (res < 0) {
+		dev_warn(&client->dev, "Write to register 0x%02x failed! "
+			 "Please report to the driver maintainer.\n", reg);
+	}
+
+	return res;
+}
+
+static struct dme1737_data *dme1737_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	int ix;
+	u8 lsb[5];
+
+	mutex_lock(&data->update_lock);
+
+	/* Enable a Vbat monitoring cycle every 10 mins */
+	if (time_after(jiffies, data->last_vbat + 600 * HZ) || !data->valid) {
+		dme1737_write(client, DME1737_REG_CONFIG, dme1737_read(client,
+						DME1737_REG_CONFIG) | 0x10);
+		data->last_vbat = jiffies;
+	}
+
+	/* Sample register contents every 1 sec */
+	if (time_after(jiffies, data->last_update + HZ) || !data->valid) {
+		data->vid = dme1737_read(client, DME1737_REG_VID) & 0x3f;
+
+		/* In (voltage) registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
+			/* Voltage inputs are stored as 16 bit values even
+			 * though they have only 12 bits resolution. This is
+			 * to make it consistent with the temp inputs. */
+			data->in[ix] = dme1737_read(client,
+					DME1737_REG_IN(ix)) << 8;
+			data->in_min[ix] = dme1737_read(client,
+					DME1737_REG_IN_MIN(ix));
+			data->in_max[ix] = dme1737_read(client,
+					DME1737_REG_IN_MAX(ix));
+		}
+
+		/* Temp registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) {
+			/* Temp inputs are stored as 16 bit values even
+			 * though they have only 12 bits resolution. This is
+			 * to take advantage of implicit conversions between
+			 * register values (2's complement) and temp values
+			 * (signed decimal). */
+			data->temp[ix] = dme1737_read(client,
+					DME1737_REG_TEMP(ix)) << 8;
+			data->temp_min[ix] = dme1737_read(client,
+					DME1737_REG_TEMP_MIN(ix));
+			data->temp_max[ix] = dme1737_read(client,
+					DME1737_REG_TEMP_MAX(ix));
+			data->temp_offset[ix] = dme1737_read(client,
+					DME1737_REG_TEMP_OFFSET(ix));
+		}
+
+		/* In and temp LSB registers
+		 * The LSBs are latched when the MSBs are read, so the order in
+		 * which the registers are read (MSB first, then LSB) is
+		 * important! */
+		for (ix = 0; ix < ARRAY_SIZE(lsb); ix++) {
+			lsb[ix] = dme1737_read(client,
+					DME1737_REG_IN_TEMP_LSB(ix));
+		}
+		for (ix = 0; ix < ARRAY_SIZE(data->in); ix++) {
+			data->in[ix] |= (lsb[DME1737_REG_IN_LSB[ix]] <<
+					DME1737_REG_IN_LSB_SHL[ix]) & 0xf0;
+		}
+		for (ix = 0; ix < ARRAY_SIZE(data->temp); ix++) {
+			data->temp[ix] |= (lsb[DME1737_REG_TEMP_LSB[ix]] <<
+					DME1737_REG_TEMP_LSB_SHL[ix]) & 0xf0;
+		}
+
+		/* Fan registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->fan); ix++) {
+			/* Skip reading registers if optional fans are not
+			 * present */
+			if (!(data->has_fan & (1 << ix))) {
+				continue;
+			}
+			data->fan[ix] = dme1737_read(client,
+					DME1737_REG_FAN(ix));
+			data->fan[ix] |= dme1737_read(client,
+					DME1737_REG_FAN(ix) + 1) << 8;
+			data->fan_min[ix] = dme1737_read(client,
+					DME1737_REG_FAN_MIN(ix));
+			data->fan_min[ix] |= dme1737_read(client,
+					DME1737_REG_FAN_MIN(ix) + 1) << 8;
+			data->fan_opt[ix] = dme1737_read(client,
+					DME1737_REG_FAN_OPT(ix));
+			/* fan_max exists only for fan[5-6] */
+			if (ix > 3) {
+				data->fan_max[ix - 4] = dme1737_read(client,
+					DME1737_REG_FAN_MAX(ix));
+			}
+		}
+
+		/* PWM registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->pwm); ix++) {
+			/* Skip reading registers if optional PWMs are not
+			 * present */
+			if (!(data->has_pwm & (1 << ix))) {
+				continue;
+			}
+			data->pwm[ix] = dme1737_read(client,
+					DME1737_REG_PWM(ix));
+			data->pwm_freq[ix] = dme1737_read(client,
+					DME1737_REG_PWM_FREQ(ix));
+			/* pwm_config and pwm_min exist only for pwm[1-3] */
+			if (ix < 3) {
+				data->pwm_config[ix] = dme1737_read(client,
+						DME1737_REG_PWM_CONFIG(ix));
+				data->pwm_min[ix] = dme1737_read(client,
+						DME1737_REG_PWM_MIN(ix));
+			}
+		}
+		for (ix = 0; ix < ARRAY_SIZE(data->pwm_rr); ix++) {
+			data->pwm_rr[ix] = dme1737_read(client,
+						DME1737_REG_PWM_RR(ix));
+		}
+
+		/* Thermal zone registers */
+		for (ix = 0; ix < ARRAY_SIZE(data->zone_low); ix++) {
+			data->zone_low[ix] = dme1737_read(client,
+					DME1737_REG_ZONE_LOW(ix));
+			data->zone_abs[ix] = dme1737_read(client,
+					DME1737_REG_ZONE_ABS(ix));
+		}
+		for (ix = 0; ix < ARRAY_SIZE(data->zone_hyst); ix++) {
+			data->zone_hyst[ix] = dme1737_read(client,
+						DME1737_REG_ZONE_HYST(ix));
+		}
+
+		/* Alarm registers */
+		data->alarms = dme1737_read(client,
+						DME1737_REG_ALARM1);
+		/* Bit 7 tells us if the other alarm registers are non-zero and
+		 * therefore also need to be read */
+		if (data->alarms & 0x80) {
+			data->alarms |= dme1737_read(client,
+						DME1737_REG_ALARM2) << 8;
+			data->alarms |= dme1737_read(client,
+						DME1737_REG_ALARM3) << 16;
+		}
+
+		data->last_update = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+/* ---------------------------------------------------------------------
+ * Voltage sysfs attributes
+ * ix = [0-5]
+ * --------------------------------------------------------------------- */
+
+#define SYS_IN_INPUT	0
+#define SYS_IN_MIN	1
+#define SYS_IN_MAX	2
+#define SYS_IN_ALARM	3
+
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+		       char *buf)
+{
+	struct dme1737_data *data = dme1737_update_device(dev);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SYS_IN_INPUT:
+		res = IN_FROM_REG(data->in[ix], ix, 16);
+		break;
+	case SYS_IN_MIN:
+		res = IN_FROM_REG(data->in_min[ix], ix, 8);
+		break;
+	case SYS_IN_MAX:
+		res = IN_FROM_REG(data->in_max[ix], ix, 8);
+		break;
+	case SYS_IN_ALARM:
+		res = (data->alarms >> DME1737_BIT_ALARM_IN[ix]) & 0x01;
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_in(struct device *dev, struct device_attribute *attr,
+		      const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SYS_IN_MIN:
+		data->in_min[ix] = IN_TO_REG(val, ix);
+		dme1737_write(client, DME1737_REG_IN_MIN(ix),
+			      data->in_min[ix]);
+		break;
+	case SYS_IN_MAX:
+		data->in_max[ix] = IN_TO_REG(val, ix);
+		dme1737_write(client, DME1737_REG_IN_MAX(ix),
+			      data->in_max[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Temperature sysfs attributes
+ * ix = [0-2]
+ * --------------------------------------------------------------------- */
+
+#define SYS_TEMP_INPUT			0
+#define SYS_TEMP_MIN			1
+#define SYS_TEMP_MAX			2
+#define SYS_TEMP_OFFSET			3
+#define SYS_TEMP_ALARM			4
+#define SYS_TEMP_FAULT			5
+
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct dme1737_data *data = dme1737_update_device(dev);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SYS_TEMP_INPUT:
+		res = TEMP_FROM_REG(data->temp[ix], 16);
+		break;
+	case SYS_TEMP_MIN:
+		res = TEMP_FROM_REG(data->temp_min[ix], 8);
+		break;
+	case SYS_TEMP_MAX:
+		res = TEMP_FROM_REG(data->temp_max[ix], 8);
+		break;
+	case SYS_TEMP_OFFSET:
+		res = TEMP_FROM_REG(data->temp_offset[ix], 8);
+		break;
+	case SYS_TEMP_ALARM:
+		res = (data->alarms >> DME1737_BIT_ALARM_TEMP[ix]) & 0x01;
+		break;
+	case SYS_TEMP_FAULT:
+		res = (((u16)data->temp[ix] & 0xff00) == 0x8000);
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_temp(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SYS_TEMP_MIN:
+		data->temp_min[ix] = TEMP_TO_REG(val);
+		dme1737_write(client, DME1737_REG_TEMP_MIN(ix),
+			      data->temp_min[ix]);
+		break;
+	case SYS_TEMP_MAX:
+		data->temp_max[ix] = TEMP_TO_REG(val);
+		dme1737_write(client, DME1737_REG_TEMP_MAX(ix),
+			      data->temp_max[ix]);
+		break;
+	case SYS_TEMP_OFFSET:
+		data->temp_offset[ix] = TEMP_TO_REG(val);
+		dme1737_write(client, DME1737_REG_TEMP_OFFSET(ix),
+			      data->temp_offset[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Zone sysfs attributes
+ * ix = [0-2]
+ * --------------------------------------------------------------------- */
+
+#define SYS_ZONE_AUTO_CHANNELS_TEMP	0
+#define SYS_ZONE_AUTO_POINT1_TEMP_HYST	1
+#define SYS_ZONE_AUTO_POINT1_TEMP	2
+#define SYS_ZONE_AUTO_POINT2_TEMP	3
+#define SYS_ZONE_AUTO_POINT3_TEMP	4
+
+static ssize_t show_zone(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct dme1737_data *data = dme1737_update_device(dev);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SYS_ZONE_AUTO_CHANNELS_TEMP:
+		/* check config2 for non-standard temp-to-zone mapping */
+		if ((ix == 1) && (data->config2 & 0x02)) {
+			res = 4;
+		} else {
+			res = 1 << ix;
+		}
+		break;
+	case SYS_ZONE_AUTO_POINT1_TEMP_HYST:
+		res = TEMP_FROM_REG(data->zone_low[ix], 8) -
+		      TEMP_HYST_FROM_REG(data->zone_hyst[ix == 2], ix);
+		break;
+	case SYS_ZONE_AUTO_POINT1_TEMP:
+		res = TEMP_FROM_REG(data->zone_low[ix], 8);
+		break;
+	case SYS_ZONE_AUTO_POINT2_TEMP:
+		/* pwm_freq holds the temp range bits in the upper nibble */
+		res = TEMP_FROM_REG(data->zone_low[ix], 8) +
+		      TEMP_RANGE_FROM_REG(data->pwm_freq[ix]);
+		break;
+	case SYS_ZONE_AUTO_POINT3_TEMP:
+		res = TEMP_FROM_REG(data->zone_abs[ix], 8);
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_zone(struct device *dev, struct device_attribute *attr,
+			const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SYS_ZONE_AUTO_POINT1_TEMP_HYST:
+		/* Refresh the cache */
+		data->zone_low[ix] = dme1737_read(client,
+						  DME1737_REG_ZONE_LOW(ix));
+		/* Modify the temp hyst value */
+		data->zone_hyst[ix == 2] = TEMP_HYST_TO_REG(
+					TEMP_FROM_REG(data->zone_low[ix], 8) -
+					val, ix, dme1737_read(client,
+					DME1737_REG_ZONE_HYST(ix == 2)));
+		dme1737_write(client, DME1737_REG_ZONE_HYST(ix == 2),
+			      data->zone_hyst[ix == 2]);
+		break;
+	case SYS_ZONE_AUTO_POINT1_TEMP:
+		data->zone_low[ix] = TEMP_TO_REG(val);
+		dme1737_write(client, DME1737_REG_ZONE_LOW(ix),
+			      data->zone_low[ix]);
+		break;
+	case SYS_ZONE_AUTO_POINT2_TEMP:
+		/* Refresh the cache */
+		data->zone_low[ix] = dme1737_read(client,
+						  DME1737_REG_ZONE_LOW(ix));
+		/* Modify the temp range value (which is stored in the upper
+		 * nibble of the pwm_freq register) */
+		data->pwm_freq[ix] = TEMP_RANGE_TO_REG(val -
+					TEMP_FROM_REG(data->zone_low[ix], 8),
+					dme1737_read(client,
+					DME1737_REG_PWM_FREQ(ix)));
+		dme1737_write(client, DME1737_REG_PWM_FREQ(ix),
+			      data->pwm_freq[ix]);
+		break;
+	case SYS_ZONE_AUTO_POINT3_TEMP:
+		data->zone_abs[ix] = TEMP_TO_REG(val);
+		dme1737_write(client, DME1737_REG_ZONE_ABS(ix),
+			      data->zone_abs[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Fan sysfs attributes
+ * ix = [0-5]
+ * --------------------------------------------------------------------- */
+
+#define SYS_FAN_INPUT	0
+#define SYS_FAN_MIN	1
+#define SYS_FAN_MAX	2
+#define SYS_FAN_ALARM	3
+#define SYS_FAN_TYPE	4
+
+static ssize_t show_fan(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct dme1737_data *data = dme1737_update_device(dev);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SYS_FAN_INPUT:
+		res = FAN_FROM_REG(data->fan[ix],
+				   ix < 4 ? 0 :
+				   FAN_TPC_FROM_REG(data->fan_opt[ix]));
+		break;
+	case SYS_FAN_MIN:
+		res = FAN_FROM_REG(data->fan_min[ix],
+				   ix < 4 ? 0 :
+				   FAN_TPC_FROM_REG(data->fan_opt[ix]));
+		break;
+	case SYS_FAN_MAX:
+		/* only valid for fan[5-6] */
+		res = FAN_MAX_FROM_REG(data->fan_max[ix - 4]);
+		break;
+	case SYS_FAN_ALARM:
+		res = (data->alarms >> DME1737_BIT_ALARM_FAN[ix]) & 0x01;
+		break;
+	case SYS_FAN_TYPE:
+		/* only valid for fan[1-4] */
+		res = FAN_TYPE_FROM_REG(data->fan_opt[ix]);
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static ssize_t set_fan(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SYS_FAN_MIN:
+		if (ix < 4) {
+			data->fan_min[ix] = FAN_TO_REG(val, 0);
+		} else {
+			/* Refresh the cache */
+			data->fan_opt[ix] = dme1737_read(client,
+						DME1737_REG_FAN_OPT(ix));
+			/* Modify the fan min value */
+			data->fan_min[ix] = FAN_TO_REG(val,
+					FAN_TPC_FROM_REG(data->fan_opt[ix]));
+		}
+		dme1737_write(client, DME1737_REG_FAN_MIN(ix),
+			      data->fan_min[ix] & 0xff);
+		dme1737_write(client, DME1737_REG_FAN_MIN(ix) + 1,
+			      data->fan_min[ix] >> 8);
+		break;
+	case SYS_FAN_MAX:
+		/* Only valid for fan[5-6] */
+		data->fan_max[ix - 4] = FAN_MAX_TO_REG(val);
+		dme1737_write(client, DME1737_REG_FAN_MAX(ix),
+			      data->fan_max[ix - 4]);
+		break;
+	case SYS_FAN_TYPE:
+		/* Only valid for fan[1-4] */
+		if (!(val == 1 || val == 2 || val == 4)) {
+			count = -EINVAL;
+			dev_warn(&client->dev, "Fan type value %ld not "
+				 "supported. Choose one of 1, 2, or 4.\n",
+				 val);
+			goto exit;
+		}
+		data->fan_opt[ix] = FAN_TYPE_TO_REG(val, dme1737_read(client,
+					DME1737_REG_FAN_OPT(ix)));
+		dme1737_write(client, DME1737_REG_FAN_OPT(ix),
+			      data->fan_opt[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+exit:
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * PWM sysfs attributes
+ * ix = [0-4]
+ * --------------------------------------------------------------------- */
+
+#define SYS_PWM				0
+#define SYS_PWM_FREQ			1
+#define SYS_PWM_ENABLE			2
+#define SYS_PWM_RAMP_RATE		3
+#define SYS_PWM_AUTO_CHANNELS_ZONE	4
+#define SYS_PWM_AUTO_PWM_MIN		5
+#define SYS_PWM_AUTO_POINT1_PWM		6
+#define SYS_PWM_AUTO_POINT2_PWM		7
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct dme1737_data *data = dme1737_update_device(dev);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	int res;
+
+	switch (fn) {
+	case SYS_PWM:
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 0) {
+			res = 255;
+		} else {
+			res = data->pwm[ix];
+		}
+		break;
+	case SYS_PWM_FREQ:
+		res = PWM_FREQ_FROM_REG(data->pwm_freq[ix]);
+		break;
+	case SYS_PWM_ENABLE:
+		if (ix > 3) {
+			res = 1; /* pwm[5-6] hard-wired to manual mode */
+		} else {
+			res = PWM_EN_FROM_REG(data->pwm_config[ix]);
+		}
+		break;
+	case SYS_PWM_RAMP_RATE:
+		/* Only valid for pwm[1-3] */
+		res = PWM_RR_FROM_REG(data->pwm_rr[ix > 0], ix);
+		break;
+	case SYS_PWM_AUTO_CHANNELS_ZONE:
+		/* Only valid for pwm[1-3] */
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
+			res = PWM_ACZ_FROM_REG(data->pwm_config[ix]);
+		} else {
+			res = data->pwm_acz[ix];
+		}
+		break;
+	case SYS_PWM_AUTO_PWM_MIN:
+		/* Only valid for pwm[1-3] */
+		if (PWM_OFF_FROM_REG(data->pwm_rr[0], ix)) {
+			res = data->pwm_min[ix];
+		} else {
+			res = 0;
+		}
+		break;
+	case SYS_PWM_AUTO_POINT1_PWM:
+		/* Only valid for pwm[1-3] */
+		res = data->pwm_min[ix];
+		break;
+	case SYS_PWM_AUTO_POINT2_PWM:
+		/* Only valid for pwm[1-3] */
+		res = 255; /* hard-wired */
+		break;
+	default:
+		res = 0;
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+
+	return sprintf(buf, "%d\n", res);
+}
+
+static struct attribute *dme1737_attr_pwm[];
+static void dme1737_chmod_file(struct i2c_client*, struct attribute*, mode_t);
+
+static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	struct sensor_device_attribute_2
+		*sensor_attr_2 = to_sensor_dev_attr_2(attr);
+	int ix = sensor_attr_2->index;
+	int fn = sensor_attr_2->nr;
+	long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	switch (fn) {
+	case SYS_PWM:
+		data->pwm[ix] = SENSORS_LIMIT(val, 0, 255);
+		dme1737_write(client, DME1737_REG_PWM(ix), data->pwm[ix]);
+		break;
+	case SYS_PWM_FREQ:
+		data->pwm_freq[ix] = PWM_FREQ_TO_REG(val, dme1737_read(client,
+						DME1737_REG_PWM_FREQ(ix)));
+		dme1737_write(client, DME1737_REG_PWM_FREQ(ix),
+			      data->pwm_freq[ix]);
+		break;
+	case SYS_PWM_ENABLE:
+		/* Only valid for pwm[1-3] */
+		if (val < 0 || val > 2) {
+			count = -EINVAL;
+			dev_warn(&client->dev, "PWM enable %ld not "
+				 "supported. Choose one of 0, 1, or 2.\n",
+				 val);
+			goto exit;
+		}
+		/* Refresh the cache */
+		data->pwm_config[ix] = dme1737_read(client,
+						DME1737_REG_PWM_CONFIG(ix));
+		if (val == PWM_EN_FROM_REG(data->pwm_config[ix])) {
+			/* Bail out if no change */
+			goto exit;
+		}
+		/* Do some housekeeping if we are currently in auto mode */
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
+			/* Save the current zone channel assignment */
+			data->pwm_acz[ix] = PWM_ACZ_FROM_REG(
+							data->pwm_config[ix]);
+			/* Save the current ramp rate state and disable it */
+			data->pwm_rr[ix > 0] = dme1737_read(client,
+						DME1737_REG_PWM_RR(ix > 0));
+			data->pwm_rr_en &= ~(1 << ix);
+			if (PWM_RR_EN_FROM_REG(data->pwm_rr[ix > 0], ix)) {
+				data->pwm_rr_en |= (1 << ix);
+				data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(0, ix,
+							data->pwm_rr[ix > 0]);
+				dme1737_write(client,
+					      DME1737_REG_PWM_RR(ix > 0),
+					      data->pwm_rr[ix > 0]);
+			}
+		}
+		/* Set the new PWM mode */
+		switch (val) {
+		case 0:
+			/* Change permissions of pwm[ix] to read-only */
+			dme1737_chmod_file(client, dme1737_attr_pwm[ix],
+					   S_IRUGO);
+			/* Turn fan fully on */
+			data->pwm_config[ix] = PWM_EN_TO_REG(0,
+							data->pwm_config[ix]);
+			dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+				      data->pwm_config[ix]);
+			break;
+		case 1:
+			/* Turn on manual mode */
+			data->pwm_config[ix] = PWM_EN_TO_REG(1,
+							data->pwm_config[ix]);
+			dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+				      data->pwm_config[ix]);
+			/* Change permissions of pwm[ix] to read-writeable */
+			dme1737_chmod_file(client, dme1737_attr_pwm[ix],
+					   S_IRUGO | S_IWUSR);
+			break;
+		case 2:
+			/* Change permissions of pwm[ix] to read-only */
+			dme1737_chmod_file(client, dme1737_attr_pwm[ix],
+					   S_IRUGO);
+			/* Turn on auto mode using the saved zone channel
+			 * assignment */
+			data->pwm_config[ix] = PWM_ACZ_TO_REG(
+							data->pwm_acz[ix],
+							data->pwm_config[ix]);
+			dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+				      data->pwm_config[ix]);
+			/* Enable PWM ramp rate if previously enabled */
+			if (data->pwm_rr_en & (1 << ix)) {
+				data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(1, ix,
+						dme1737_read(client,
+						DME1737_REG_PWM_RR(ix > 0)));
+				dme1737_write(client,
+					      DME1737_REG_PWM_RR(ix > 0),
+					      data->pwm_rr[ix > 0]);
+			}
+			break;
+		}
+		break;
+	case SYS_PWM_RAMP_RATE:
+		/* Only valid for pwm[1-3] */
+		/* Refresh the cache */
+		data->pwm_config[ix] = dme1737_read(client,
+						DME1737_REG_PWM_CONFIG(ix));
+		data->pwm_rr[ix > 0] = dme1737_read(client,
+						DME1737_REG_PWM_RR(ix > 0));
+		/* Set the ramp rate value */
+		if (val > 0) {
+			data->pwm_rr[ix > 0] = PWM_RR_TO_REG(val, ix,
+							data->pwm_rr[ix > 0]);
+		}
+		/* Enable/disable the feature only if the associated PWM
+		 * output is in automatic mode. */
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
+			data->pwm_rr[ix > 0] = PWM_RR_EN_TO_REG(val > 0, ix,
+							data->pwm_rr[ix > 0]);
+		}
+		dme1737_write(client, DME1737_REG_PWM_RR(ix > 0),
+			      data->pwm_rr[ix > 0]);
+		break;
+	case SYS_PWM_AUTO_CHANNELS_ZONE:
+		/* Only valid for pwm[1-3] */
+		if (!(val == 1 || val == 2 || val == 4 ||
+		      val == 6 || val == 7)) {
+			count = -EINVAL;
+			dev_warn(&client->dev, "PWM auto channels zone %ld "
+				 "not supported. Choose one of 1, 2, 4, 6, "
+				 "or 7.\n", val);
+			goto exit;
+		}
+		/* Refresh the cache */
+		data->pwm_config[ix] = dme1737_read(client,
+						DME1737_REG_PWM_CONFIG(ix));
+		if (PWM_EN_FROM_REG(data->pwm_config[ix]) == 2) {
+			/* PWM is already in auto mode so update the temp
+			 * channel assignment */
+			data->pwm_config[ix] = PWM_ACZ_TO_REG(val,
+						data->pwm_config[ix]);
+			dme1737_write(client, DME1737_REG_PWM_CONFIG(ix),
+				      data->pwm_config[ix]);
+		} else {
+			/* PWM is not in auto mode so we save the temp
+			 * channel assignment for later use */
+			data->pwm_acz[ix] = val;
+		}
+		break;
+	case SYS_PWM_AUTO_PWM_MIN:
+		/* Only valid for pwm[1-3] */
+		/* Refresh the cache */
+		data->pwm_min[ix] = dme1737_read(client,
+						DME1737_REG_PWM_MIN(ix));
+		/* There are only 2 values supported for the auto_pwm_min
+		 * value: 0 or auto_point1_pwm. So if the temperature drops
+		 * below the auto_point1_temp_hyst value, the fan either turns
+		 * off or runs at auto_point1_pwm duty-cycle. */
+		if (val > ((data->pwm_min[ix] + 1) / 2)) {
+			data->pwm_rr[0] = PWM_OFF_TO_REG(1, ix,
+						dme1737_read(client,
+						DME1737_REG_PWM_RR(0)));
+
+		} else {
+			data->pwm_rr[0] = PWM_OFF_TO_REG(0, ix,
+						dme1737_read(client,
+						DME1737_REG_PWM_RR(0)));
+
+		}
+		dme1737_write(client, DME1737_REG_PWM_RR(0),
+			      data->pwm_rr[0]);
+		break;
+	case SYS_PWM_AUTO_POINT1_PWM:
+		/* Only valid for pwm[1-3] */
+		data->pwm_min[ix] = SENSORS_LIMIT(val, 0, 255);
+		dme1737_write(client, DME1737_REG_PWM_MIN(ix),
+			      data->pwm_min[ix]);
+		break;
+	default:
+		dev_dbg(dev, "Unknown attr fetch (%d)\n", fn);
+	}
+exit:
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+/* ---------------------------------------------------------------------
+ * Miscellaneous sysfs attributes
+ * --------------------------------------------------------------------- */
+
+static ssize_t show_vrm(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+
+	return sprintf(buf, "%d\n", data->vrm);
+}
+
+static ssize_t set_vrm(struct device *dev, struct device_attribute *attr,
+		       const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	long val = simple_strtol(buf, NULL, 10);
+
+	data->vrm = val;
+	return count;
+}
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	struct dme1737_data *data = dme1737_update_device(dev);
+
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+
+/* ---------------------------------------------------------------------
+ * Sysfs device attribute defines and structs
+ * --------------------------------------------------------------------- */
+
+/* Voltages 0-6 */
+
+#define SENSOR_DEVICE_ATTR_IN(ix) \
+static SENSOR_DEVICE_ATTR_2(in##ix##_input, S_IRUGO, \
+        show_in, NULL, SYS_IN_INPUT, ix); \
+static SENSOR_DEVICE_ATTR_2(in##ix##_min, S_IRUGO | S_IWUSR, \
+        show_in, set_in, SYS_IN_MIN, ix); \
+static SENSOR_DEVICE_ATTR_2(in##ix##_max, S_IRUGO | S_IWUSR, \
+        show_in, set_in, SYS_IN_MAX, ix); \
+static SENSOR_DEVICE_ATTR_2(in##ix##_alarm, S_IRUGO, \
+        show_in, NULL, SYS_IN_ALARM, ix)
+
+SENSOR_DEVICE_ATTR_IN(0);
+SENSOR_DEVICE_ATTR_IN(1);
+SENSOR_DEVICE_ATTR_IN(2);
+SENSOR_DEVICE_ATTR_IN(3);
+SENSOR_DEVICE_ATTR_IN(4);
+SENSOR_DEVICE_ATTR_IN(5);
+SENSOR_DEVICE_ATTR_IN(6);
+
+/* Temperatures 1-3 */
+
+#define SENSOR_DEVICE_ATTR_TEMP(ix) \
+static SENSOR_DEVICE_ATTR_2(temp##ix##_input, S_IRUGO, \
+        show_temp, NULL, SYS_TEMP_INPUT, ix-1); \
+static SENSOR_DEVICE_ATTR_2(temp##ix##_min, S_IRUGO | S_IWUSR, \
+        show_temp, set_temp, SYS_TEMP_MIN, ix-1); \
+static SENSOR_DEVICE_ATTR_2(temp##ix##_max, S_IRUGO | S_IWUSR, \
+        show_temp, set_temp, SYS_TEMP_MAX, ix-1); \
+static SENSOR_DEVICE_ATTR_2(temp##ix##_offset, S_IRUGO, \
+        show_temp, set_temp, SYS_TEMP_OFFSET, ix-1); \
+static SENSOR_DEVICE_ATTR_2(temp##ix##_alarm, S_IRUGO, \
+        show_temp, NULL, SYS_TEMP_ALARM, ix-1); \
+static SENSOR_DEVICE_ATTR_2(temp##ix##_fault, S_IRUGO, \
+        show_temp, NULL, SYS_TEMP_FAULT, ix-1)
+
+SENSOR_DEVICE_ATTR_TEMP(1);
+SENSOR_DEVICE_ATTR_TEMP(2);
+SENSOR_DEVICE_ATTR_TEMP(3);
+
+/* Zones 1-3 */
+
+#define SENSOR_DEVICE_ATTR_ZONE(ix) \
+static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_channels_temp, S_IRUGO, \
+        show_zone, NULL, SYS_ZONE_AUTO_CHANNELS_TEMP, ix-1); \
+static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point1_temp_hyst, S_IRUGO, \
+        show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP_HYST, ix-1); \
+static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point1_temp, S_IRUGO, \
+        show_zone, set_zone, SYS_ZONE_AUTO_POINT1_TEMP, ix-1); \
+static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point2_temp, S_IRUGO, \
+        show_zone, set_zone, SYS_ZONE_AUTO_POINT2_TEMP, ix-1); \
+static SENSOR_DEVICE_ATTR_2(zone##ix##_auto_point3_temp, S_IRUGO, \
+        show_zone, set_zone, SYS_ZONE_AUTO_POINT3_TEMP, ix-1)
+
+SENSOR_DEVICE_ATTR_ZONE(1);
+SENSOR_DEVICE_ATTR_ZONE(2);
+SENSOR_DEVICE_ATTR_ZONE(3);
+
+/* Fans 1-4 */
+
+#define SENSOR_DEVICE_ATTR_FAN_1TO4(ix) \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_input, S_IRUGO, \
+        show_fan, NULL, SYS_FAN_INPUT, ix-1); \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \
+        show_fan, set_fan, SYS_FAN_MIN, ix-1); \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_alarm, S_IRUGO, \
+        show_fan, NULL, SYS_FAN_ALARM, ix-1); \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_type, S_IRUGO | S_IWUSR, \
+        show_fan, set_fan, SYS_FAN_TYPE, ix-1)
+
+SENSOR_DEVICE_ATTR_FAN_1TO4(1);
+SENSOR_DEVICE_ATTR_FAN_1TO4(2);
+SENSOR_DEVICE_ATTR_FAN_1TO4(3);
+SENSOR_DEVICE_ATTR_FAN_1TO4(4);
+
+/* Fans 5-6 */
+
+#define SENSOR_DEVICE_ATTR_FAN_5TO6(ix) \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_input, S_IRUGO, \
+        show_fan, NULL, SYS_FAN_INPUT, ix-1); \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_min, S_IRUGO | S_IWUSR, \
+        show_fan, set_fan, SYS_FAN_MIN, ix-1); \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_alarm, S_IRUGO, \
+        show_fan, NULL, SYS_FAN_ALARM, ix-1); \
+static SENSOR_DEVICE_ATTR_2(fan##ix##_max, S_IRUGO | S_IWUSR, \
+        show_fan, set_fan, SYS_FAN_MAX, ix-1)
+
+SENSOR_DEVICE_ATTR_FAN_5TO6(5);
+SENSOR_DEVICE_ATTR_FAN_5TO6(6);
+
+/* PWMs 1-3 */
+
+#define SENSOR_DEVICE_ATTR_PWM_1TO3(ix) \
+static SENSOR_DEVICE_ATTR_2(pwm##ix, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_freq, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_enable, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM_ENABLE, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_ramp_rate, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM_RAMP_RATE, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_channels_zone, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM_AUTO_CHANNELS_ZONE, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_pwm_min, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM_AUTO_PWM_MIN, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_point1_pwm, S_IRUGO, \
+        show_pwm, set_pwm, SYS_PWM_AUTO_POINT1_PWM, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_auto_point2_pwm, S_IRUGO, \
+        show_pwm, NULL, SYS_PWM_AUTO_POINT2_PWM, ix-1)
+
+SENSOR_DEVICE_ATTR_PWM_1TO3(1);
+SENSOR_DEVICE_ATTR_PWM_1TO3(2);
+SENSOR_DEVICE_ATTR_PWM_1TO3(3);
+
+/* PWMs 5-6 */
+
+#define SENSOR_DEVICE_ATTR_PWM_5TO6(ix) \
+static SENSOR_DEVICE_ATTR_2(pwm##ix, S_IRUGO | S_IWUSR, \
+        show_pwm, set_pwm, SYS_PWM, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_freq, S_IRUGO | S_IWUSR, \
+        show_pwm, set_pwm, SYS_PWM_FREQ, ix-1); \
+static SENSOR_DEVICE_ATTR_2(pwm##ix##_enable, S_IRUGO, \
+        show_pwm, NULL, SYS_PWM_ENABLE, ix-1)
+
+SENSOR_DEVICE_ATTR_PWM_5TO6(5);
+SENSOR_DEVICE_ATTR_PWM_5TO6(6);
+
+/* Misc */
+
+static DEVICE_ATTR(vrm, S_IRUGO | S_IWUSR, show_vrm, set_vrm);
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
+#define SENSOR_DEV_ATTR_IN(ix) \
+&sensor_dev_attr_in##ix##_input.dev_attr.attr, \
+&sensor_dev_attr_in##ix##_min.dev_attr.attr, \
+&sensor_dev_attr_in##ix##_max.dev_attr.attr, \
+&sensor_dev_attr_in##ix##_alarm.dev_attr.attr
+
+/* These attributes are read-writeable only if the chip is *not* locked */
+#define SENSOR_DEV_ATTR_TEMP_LOCK(ix) \
+&sensor_dev_attr_temp##ix##_offset.dev_attr.attr
+
+#define SENSOR_DEV_ATTR_TEMP(ix) \
+SENSOR_DEV_ATTR_TEMP_LOCK(ix), \
+&sensor_dev_attr_temp##ix##_input.dev_attr.attr, \
+&sensor_dev_attr_temp##ix##_min.dev_attr.attr, \
+&sensor_dev_attr_temp##ix##_max.dev_attr.attr, \
+&sensor_dev_attr_temp##ix##_alarm.dev_attr.attr, \
+&sensor_dev_attr_temp##ix##_fault.dev_attr.attr
+
+/* These attributes are read-writeable only if the chip is *not* locked */
+#define SENSOR_DEV_ATTR_ZONE_LOCK(ix) \
+&sensor_dev_attr_zone##ix##_auto_point1_temp_hyst.dev_attr.attr, \
+&sensor_dev_attr_zone##ix##_auto_point1_temp.dev_attr.attr, \
+&sensor_dev_attr_zone##ix##_auto_point2_temp.dev_attr.attr, \
+&sensor_dev_attr_zone##ix##_auto_point3_temp.dev_attr.attr
+
+#define SENSOR_DEV_ATTR_ZONE(ix) \
+SENSOR_DEV_ATTR_ZONE_LOCK(ix), \
+&sensor_dev_attr_zone##ix##_auto_channels_temp.dev_attr.attr
+
+#define SENSOR_DEV_ATTR_FAN_1TO4(ix) \
+&sensor_dev_attr_fan##ix##_input.dev_attr.attr, \
+&sensor_dev_attr_fan##ix##_min.dev_attr.attr, \
+&sensor_dev_attr_fan##ix##_alarm.dev_attr.attr, \
+&sensor_dev_attr_fan##ix##_type.dev_attr.attr
+
+#define SENSOR_DEV_ATTR_FAN_5TO6(ix) \
+&sensor_dev_attr_fan##ix##_input.dev_attr.attr, \
+&sensor_dev_attr_fan##ix##_min.dev_attr.attr, \
+&sensor_dev_attr_fan##ix##_alarm.dev_attr.attr, \
+&sensor_dev_attr_fan##ix##_max.dev_attr.attr
+
+/* These attributes are read-writeable only if the chip is *not* locked */
+#define SENSOR_DEV_ATTR_PWM_1TO3_LOCK(ix) \
+&sensor_dev_attr_pwm##ix##_freq.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_enable.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_ramp_rate.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_auto_channels_zone.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_auto_pwm_min.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_auto_point1_pwm.dev_attr.attr
+
+#define SENSOR_DEV_ATTR_PWM_1TO3(ix) \
+SENSOR_DEV_ATTR_PWM_1TO3_LOCK(ix), \
+&sensor_dev_attr_pwm##ix.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_auto_point2_pwm.dev_attr.attr
+
+/* These attributes are read-writeable only if the chip is *not* locked */
+#define SENSOR_DEV_ATTR_PWM_5TO6_LOCK(ix) \
+&sensor_dev_attr_pwm##ix.dev_attr.attr, \
+&sensor_dev_attr_pwm##ix##_freq.dev_attr.attr
+
+#define SENSOR_DEV_ATTR_PWM_5TO6(ix) \
+SENSOR_DEV_ATTR_PWM_5TO6_LOCK(ix), \
+&sensor_dev_attr_pwm##ix##_enable.dev_attr.attr
+
+/* This struct holds all the attributes that are always present and need to be
+ * created unconditionally. The attributes that need modification of their
+ * permissions are created read-only and write permissions are added or removed
+ * on the fly when required */
+static struct attribute *dme1737_attr[] ={
+        /* Voltages */
+        SENSOR_DEV_ATTR_IN(0),
+        SENSOR_DEV_ATTR_IN(1),
+        SENSOR_DEV_ATTR_IN(2),
+        SENSOR_DEV_ATTR_IN(3),
+        SENSOR_DEV_ATTR_IN(4),
+        SENSOR_DEV_ATTR_IN(5),
+        SENSOR_DEV_ATTR_IN(6),
+        /* Temperatures */
+        SENSOR_DEV_ATTR_TEMP(1),
+        SENSOR_DEV_ATTR_TEMP(2),
+        SENSOR_DEV_ATTR_TEMP(3),
+        /* Zones */
+        SENSOR_DEV_ATTR_ZONE(1),
+        SENSOR_DEV_ATTR_ZONE(2),
+        SENSOR_DEV_ATTR_ZONE(3),
+        /* Misc */
+        &dev_attr_vrm.attr,
+        &dev_attr_cpu0_vid.attr,
+	NULL
+};
+
+static const struct attribute_group dme1737_group = {
+        .attrs = dme1737_attr,
+};
+
+/* The following structs hold the PWM attributes, some of which are optional.
+ * Their creation depends on the chip configuration which is determined during
+ * module load. */
+static struct attribute *dme1737_attr_pwm1[] = {
+        SENSOR_DEV_ATTR_PWM_1TO3(1),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm2[] = {
+        SENSOR_DEV_ATTR_PWM_1TO3(2),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm3[] = {
+        SENSOR_DEV_ATTR_PWM_1TO3(3),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm5[] = {
+        SENSOR_DEV_ATTR_PWM_5TO6(5),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm6[] = {
+        SENSOR_DEV_ATTR_PWM_5TO6(6),
+	NULL
+};
+
+static const struct attribute_group dme1737_pwm_group[] = {
+	{ .attrs = dme1737_attr_pwm1 },
+	{ .attrs = dme1737_attr_pwm2 },
+	{ .attrs = dme1737_attr_pwm3 },
+	{ .attrs = NULL },
+	{ .attrs = dme1737_attr_pwm5 },
+	{ .attrs = dme1737_attr_pwm6 },
+};
+
+/* The following structs hold the fan attributes, some of which are optional.
+ * Their creation depends on the chip configuration which is determined during
+ * module load. */
+static struct attribute *dme1737_attr_fan1[] = {
+        SENSOR_DEV_ATTR_FAN_1TO4(1),
+	NULL
+};
+static struct attribute *dme1737_attr_fan2[] = {
+        SENSOR_DEV_ATTR_FAN_1TO4(2),
+	NULL
+};
+static struct attribute *dme1737_attr_fan3[] = {
+        SENSOR_DEV_ATTR_FAN_1TO4(3),
+	NULL
+};
+static struct attribute *dme1737_attr_fan4[] = {
+        SENSOR_DEV_ATTR_FAN_1TO4(4),
+	NULL
+};
+static struct attribute *dme1737_attr_fan5[] = {
+        SENSOR_DEV_ATTR_FAN_5TO6(5),
+	NULL
+};
+static struct attribute *dme1737_attr_fan6[] = {
+        SENSOR_DEV_ATTR_FAN_5TO6(6),
+	NULL
+};
+
+static const struct attribute_group dme1737_fan_group[] = {
+	{ .attrs = dme1737_attr_fan1 },
+	{ .attrs = dme1737_attr_fan2 },
+	{ .attrs = dme1737_attr_fan3 },
+	{ .attrs = dme1737_attr_fan4 },
+	{ .attrs = dme1737_attr_fan5 },
+	{ .attrs = dme1737_attr_fan6 },
+};
+
+/* The permissions of all of the following attributes are changed to read-
+ * writeable if the chip is *not* locked. Otherwise they stay read-only. */
+static struct attribute *dme1737_attr_lock[] = {
+	/* Temperatures */
+	SENSOR_DEV_ATTR_TEMP_LOCK(1),
+	SENSOR_DEV_ATTR_TEMP_LOCK(2),
+	SENSOR_DEV_ATTR_TEMP_LOCK(3),
+	/* Zones */
+	SENSOR_DEV_ATTR_ZONE_LOCK(1),
+	SENSOR_DEV_ATTR_ZONE_LOCK(2),
+	SENSOR_DEV_ATTR_ZONE_LOCK(3),
+	NULL
+};
+
+static const struct attribute_group dme1737_lock_group = {
+	.attrs = dme1737_attr_lock,
+};
+
+/* The permissions of the following PWM attributes are changed to read-
+ * writeable if the chip is *not* locked and the respective PWM is available.
+ * Otherwise they stay read-only. */
+static struct attribute *dme1737_attr_pwm1_lock[] = {
+        SENSOR_DEV_ATTR_PWM_1TO3_LOCK(1),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm2_lock[] = {
+        SENSOR_DEV_ATTR_PWM_1TO3_LOCK(2),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm3_lock[] = {
+        SENSOR_DEV_ATTR_PWM_1TO3_LOCK(3),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm5_lock[] = {
+        SENSOR_DEV_ATTR_PWM_5TO6_LOCK(5),
+	NULL
+};
+static struct attribute *dme1737_attr_pwm6_lock[] = {
+        SENSOR_DEV_ATTR_PWM_5TO6_LOCK(6),
+	NULL
+};
+
+static const struct attribute_group dme1737_pwm_lock_group[] = {
+	{ .attrs = dme1737_attr_pwm1_lock },
+	{ .attrs = dme1737_attr_pwm2_lock },
+	{ .attrs = dme1737_attr_pwm3_lock },
+	{ .attrs = NULL },
+	{ .attrs = dme1737_attr_pwm5_lock },
+	{ .attrs = dme1737_attr_pwm6_lock },
+};
+
+/* Pwm[1-3] are read-writeable if the associated pwm is in manual mode and the
+ * chip is not locked. Otherwise they are read-only. */
+static struct attribute *dme1737_attr_pwm[] = {
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm3.dev_attr.attr,
+};
+
+/* ---------------------------------------------------------------------
+ * Super-IO functions
+ * --------------------------------------------------------------------- */
+
+static inline int dme1737_sio_inb(int sio_cip, int reg)
+{
+	outb(reg, sio_cip);
+	return inb(sio_cip + 1);
+}
+
+static inline void dme1737_sio_outb(int sio_cip, int reg, int val)
+{
+	outb(reg, sio_cip);
+	outb(val, sio_cip + 1);
+}
+
+static int dme1737_sio_get_features(int sio_cip, struct i2c_client *client)
+{
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	int err = 0, reg;
+	u16 addr;
+
+	/* Enter configuration mode */
+	outb(0x55, sio_cip);
+
+	/* Check device ID
+	 * The DME1737 can return either 0x78 or 0x77 as its device ID. */
+	reg = dme1737_sio_inb(sio_cip, 0x20);
+	if (!(reg == 0x77 || reg == 0x78)) {
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/* Select logical device A (runtime registers) */
+	dme1737_sio_outb(sio_cip, 0x07, 0x0a);
+
+	/* Get the base address of the runtime registers */
+	if (!(addr = (dme1737_sio_inb(sio_cip, 0x60) << 8) |
+		      dme1737_sio_inb(sio_cip, 0x61))) {
+		err = -ENODEV;
+		goto exit;
+	}
+
+	/* Read the runtime registers to determine which optional features
+	 * are enabled and available. Bits [3:2] of registers 0x43-0x46 are set
+	 * to '10' if the respective feature is enabled. */
+	if ((inb(addr + 0x43) & 0x0c) == 0x08) { /* fan6 */
+		data->has_fan |= (1 << 5);
+	}
+	if ((inb(addr + 0x44) & 0x0c) == 0x08) { /* pwm6 */
+		data->has_pwm |= (1 << 5);
+	}
+	if ((inb(addr + 0x45) & 0x0c) == 0x08) { /* fan5 */
+		data->has_fan |= (1 << 4);
+	}
+	if ((inb(addr + 0x46) & 0x0c) == 0x08) { /* pwm5 */
+		data->has_pwm |= (1 << 4);
+	}
+
+exit:
+	/* Exit configuration mode */
+	outb(0xaa, sio_cip);
+
+	return err;
+}
+
+/* ---------------------------------------------------------------------
+ * Device detection, registration and initialization
+ * --------------------------------------------------------------------- */
+
+static struct i2c_driver dme1737_driver;
+
+static void dme1737_chmod_file(struct i2c_client *client,
+			       struct attribute *attr, mode_t mode)
+{
+	if (sysfs_chmod_file(&client->dev.kobj, attr, mode)) {
+		dev_warn(&client->dev, "Failed to change permissions of %s.\n",
+			 attr->name);
+	}
+}
+
+static void dme1737_chmod_group(struct i2c_client *client,
+				const struct attribute_group *group,
+				mode_t mode)
+{
+	struct attribute **attr;
+
+	for (attr = group->attrs; *attr; attr++) {
+		dme1737_chmod_file(client, *attr, mode);
+	}
+}
+
+static int dme1737_init_client(struct i2c_client *client)
+{
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	int ix;
+	u8 reg;
+
+        data->config = dme1737_read(client, DME1737_REG_CONFIG);
+        /* Inform if part is not monitoring/started */
+        if (!(data->config & 0x01)) {
+                if (!force_start) {
+                        dev_err(&client->dev, "Device is not monitoring. "
+                                "Use the force_start load parameter to "
+                                "override.\n");
+                        return -EFAULT;
+                }
+
+                /* Force monitoring */
+                data->config |= 0x01;
+                dme1737_write(client, DME1737_REG_CONFIG, data->config);
+        }
+	/* Inform if part is not ready */
+	if (!(data->config & 0x04)) {
+		dev_err(&client->dev, "Device is not ready.\n");
+		return -EFAULT;
+	}
+
+	data->config2 = dme1737_read(client, DME1737_REG_CONFIG2);
+	/* Check if optional fan3 input is enabled */
+	if (data->config2 & 0x04) {
+		data->has_fan |= (1 << 2);
+	}
+
+	/* Fan4 and pwm3 are only available if the client's I2C address
+	 * is the default 0x2e. Otherwise the I/Os associated with these
+	 * functions are used for addr enable/select. */
+	if (client->addr == 0x2e) {
+		data->has_fan |= (1 << 3);
+		data->has_pwm |= (1 << 2);
+	}
+
+	/* Determine if the optional fan[5-6] and/or pwm[5-6] are enabled.
+	 * For this, we need to query the runtime registers through the
+	 * Super-IO LPC interface. Try both config ports 0x2e and 0x4e. */
+	if (dme1737_sio_get_features(0x2e, client) &&
+	    dme1737_sio_get_features(0x4e, client)) {
+		dev_warn(&client->dev, "Failed to query Super-IO for optional "
+			 "features.\n");
+	}
+
+	/* Fan1, fan2, pwm1, and pwm2 are always present */
+	data->has_fan |= 0x03;
+	data->has_pwm |= 0x03;
+
+	dev_info(&client->dev, "Optional features: pwm3=%s, pwm5=%s, pwm6=%s, "
+		 "fan3=%s, fan4=%s, fan5=%s, fan6=%s.\n",
+		 (data->has_pwm & (1 << 2)) ? "yes" : "no",
+		 (data->has_pwm & (1 << 4)) ? "yes" : "no",
+		 (data->has_pwm & (1 << 5)) ? "yes" : "no",
+		 (data->has_fan & (1 << 2)) ? "yes" : "no",
+		 (data->has_fan & (1 << 3)) ? "yes" : "no",
+		 (data->has_fan & (1 << 4)) ? "yes" : "no",
+		 (data->has_fan & (1 << 5)) ? "yes" : "no");
+
+	reg = dme1737_read(client, DME1737_REG_TACH_PWM);
+	/* Inform if fan-to-pwm mapping differs from the default */
+	if (reg != 0xa4) {
+		dev_warn(&client->dev, "Non-standard fan to pwm mapping: "
+			 "fan1->pwm%d, fan2->pwm%d, fan3->pwm%d, "
+			 "fan4->pwm%d. Please report to the driver "
+			 "maintainer.\n",
+			 (reg & 0x03) + 1, ((reg >> 2) & 0x03) + 1,
+			 ((reg >> 4) & 0x03) + 1, ((reg >> 6) & 0x03) + 1);
+	}
+
+	/* Switch pwm[1-3] to manual mode if they are currently disabled and
+	 * set the duty-cycles to 0% (which is identical to the PWMs being
+	 * disabled). */
+	if (!(data->config & 0x02)) {
+		for (ix = 0; ix < 3; ix++) {
+			data->pwm_config[ix] = dme1737_read(client,
+						DME1737_REG_PWM_CONFIG(ix));
+			if ((data->has_pwm & (1 << ix)) &&
+			    (PWM_EN_FROM_REG(data->pwm_config[ix]) == -1)) {
+				dev_info(&client->dev, "Switching pwm%d to "
+					 "manual mode.\n", ix + 1);
+				data->pwm_config[ix] = PWM_EN_TO_REG(1,
+							data->pwm_config[ix]);
+				dme1737_write(client, DME1737_REG_PWM(ix), 0);
+				dme1737_write(client,
+					      DME1737_REG_PWM_CONFIG(ix),
+					      data->pwm_config[ix]);
+			}
+		}
+	}
+
+	/* Initialize the default PWM auto channels zone (acz) assignments */
+	data->pwm_acz[0] = 1;	/* pwm1 -> zone1 */
+	data->pwm_acz[1] = 2;	/* pwm2 -> zone2 */
+	data->pwm_acz[2] = 4;	/* pwm3 -> zone3 */
+
+	/* Set VRM */
+	data->vrm = vid_which_vrm();
+
+	return 0;
+}
+
+static int dme1737_detect(struct i2c_adapter *adapter, int address,
+			  int kind)
+{
+	u8 company, verstep = 0;
+	struct i2c_client *client;
+	struct dme1737_data *data;
+	int ix, err = 0;
+	const char *name;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		goto exit;
+	}
+
+	if (!(data = kzalloc(sizeof(struct dme1737_data), GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &dme1737_driver;
+
+	/* A negative kind means that the driver was loaded with no force
+	 * parameter (default), so we must identify the chip. */
+	if (kind < 0) {
+		company = dme1737_read(client, DME1737_REG_COMPANY);
+		verstep = dme1737_read(client, DME1737_REG_VERSTEP);
+
+		if (!((company == DME1737_COMPANY_SMSC) &&
+		      ((verstep & DME1737_VERSTEP_MASK) == DME1737_VERSTEP))) {
+			err = -ENODEV;
+			goto exit_kfree;
+		}
+	}
+
+	kind = dme1737;
+	name = "dme1737";
+
+	/* Fill in the remaining client fields and put it into the global
+	 * list */
+	strlcpy(client->name, name, I2C_NAME_SIZE);
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client))) {
+		goto exit_kfree;
+	}
+
+	/* Initialize the DME1737 chip */
+	if ((err = dme1737_init_client(client))) {
+		goto exit_detach;
+	}
+
+	/* Create standard sysfs attributes */
+	if ((err = sysfs_create_group(&client->dev.kobj, &dme1737_group))) {
+                goto exit_detach;
+	}
+
+	/* Create fan sysfs attributes */
+	for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
+		if (data->has_fan & (1 << ix)) {
+			if ((err = sysfs_create_group(&client->dev.kobj,
+						&dme1737_fan_group[ix]))) {
+				goto exit_remove;
+			}
+		}
+	}
+
+	/* Create PWM sysfs attributes */
+	for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {
+		if (data->has_pwm & (1 << ix)) {
+			if ((err = sysfs_create_group(&client->dev.kobj,
+						&dme1737_pwm_group[ix]))) {
+				goto exit_remove;
+			}
+		}
+	}
+
+	/* Inform if the device is locked. Otherwise change the permissions of
+	 * selected attributes from read-only to read-writeable. */
+	if (data->config & 0x02) {
+		dev_info(&client->dev, "Device is locked. Some attributes "
+			 "will be read-only.\n");
+	} else {
+		/* Change permissions of standard attributes */
+		dme1737_chmod_group(client, &dme1737_lock_group,
+				    S_IRUGO | S_IWUSR);
+
+		/* Change permissions of PWM attributes */
+		for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_lock_group); ix++) {
+			if (data->has_pwm & (1 << ix)) {
+				dme1737_chmod_group(client,
+						&dme1737_pwm_lock_group[ix],
+						S_IRUGO | S_IWUSR);
+			}
+		}
+
+		/* Change permissions of pwm[1-3] if in manual mode */
+		for (ix = 0; ix < 3; ix++) {
+			if ((data->has_pwm & (1 << ix)) &&
+			    (PWM_EN_FROM_REG(data->pwm_config[ix]) == 1)) {
+				dme1737_chmod_file(client,
+						   dme1737_attr_pwm[ix],
+						   S_IRUGO | S_IWUSR);
+			}
+		}
+	}
+
+	/* Register device */
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove;
+	}
+
+	dev_info(&adapter->dev, "Found a DME1737 chip at 0x%02x "
+		 "(rev 0x%02x)\n", client->addr, verstep);
+
+	return 0;
+
+exit_remove:
+	for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
+		if (data->has_fan & (1 << ix)) {
+			sysfs_remove_group(&client->dev.kobj,
+					   &dme1737_fan_group[ix]);
+		}
+	}
+	for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {
+		if (data->has_pwm & (1 << ix)) {
+			sysfs_remove_group(&client->dev.kobj,
+					   &dme1737_pwm_group[ix]);
+		}
+	}
+	sysfs_remove_group(&client->dev.kobj, &dme1737_group);
+exit_detach:
+	i2c_detach_client(client);
+exit_kfree:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int dme1737_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON)) {
+		return 0;
+	}
+
+	return i2c_probe(adapter, &addr_data, dme1737_detect);
+}
+
+static int dme1737_detach_client(struct i2c_client *client)
+{
+	struct dme1737_data *data = i2c_get_clientdata(client);
+	int ix, err;
+
+	hwmon_device_unregister(data->class_dev);
+
+	for (ix = 0; ix < ARRAY_SIZE(dme1737_fan_group); ix++) {
+		if (data->has_fan & (1 << ix)) {
+			sysfs_remove_group(&client->dev.kobj,
+					   &dme1737_fan_group[ix]);
+		}
+	}
+	for (ix = 0; ix < ARRAY_SIZE(dme1737_pwm_group); ix++) {
+		if (data->has_pwm & (1 << ix)) {
+			sysfs_remove_group(&client->dev.kobj,
+					   &dme1737_pwm_group[ix]);
+		}
+	}
+	sysfs_remove_group(&client->dev.kobj, &dme1737_group);
+
+	if ((err = i2c_detach_client(client))) {
+		return err;
+	}
+
+	kfree(data);
+	return 0;
+}
+
+static struct i2c_driver dme1737_driver = {
+	.driver = {
+		.name = "dme1737",
+	},
+	.attach_adapter	= dme1737_attach_adapter,
+	.detach_client = dme1737_detach_client,
+};
+
+static int __init dme1737_init(void)
+{
+	return i2c_add_driver(&dme1737_driver);
+}
+
+static void __exit dme1737_exit(void)
+{
+	i2c_del_driver(&dme1737_driver);
+}
+
+MODULE_AUTHOR("Juerg Haefliger <juergh@gmail.com>");
+MODULE_DESCRIPTION("DME1737 sensors");
+MODULE_LICENSE("GPL");
+
+module_init(dme1737_init);
+module_exit(dme1737_exit);
diff --git a/drivers/hwmon/ds1621.c b/drivers/hwmon/ds1621.c
index d5ac422d73b2..1212d6b7f316 100644
--- a/drivers/hwmon/ds1621.c
+++ b/drivers/hwmon/ds1621.c
@@ -27,6 +27,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
@@ -52,9 +53,11 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
 #define DS1621_REG_CONFIG_DONE		0x80
 
 /* The DS1621 registers */
-#define DS1621_REG_TEMP			0xAA /* word, RO */
-#define DS1621_REG_TEMP_MIN		0xA2 /* word, RW */
-#define DS1621_REG_TEMP_MAX		0xA1 /* word, RW */
+static const u8 DS1621_REG_TEMP[3] = {
+	0xAA,		/* input, word, RO */
+	0xA2,		/* min, word, RW */
+	0xA1,		/* max, word, RW */
+};
 #define DS1621_REG_CONF			0xAC /* byte, RW */
 #define DS1621_COM_START		0xEE /* no data */
 #define DS1621_COM_STOP			0x22 /* no data */
@@ -63,10 +66,7 @@ MODULE_PARM_DESC(polarity, "Output's polarity: 0 = active high, 1 = active low")
 #define DS1621_ALARM_TEMP_HIGH		0x40
 #define DS1621_ALARM_TEMP_LOW		0x20
 
-/* Conversions. Rounding and limit checking is only done on the TO_REG
-   variants. Note that you should be a bit careful with which arguments
-   these macros are called: arguments may be evaluated more than once.
-   Fixing this is just not worth it. */
+/* Conversions */
 #define ALARMS_FROM_REG(val) ((val) & \
                               (DS1621_ALARM_TEMP_HIGH | DS1621_ALARM_TEMP_LOW))
 
@@ -78,7 +78,7 @@ struct ds1621_data {
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
-	u16 temp, temp_min, temp_max;	/* Register values, word */
+	u16 temp[3];			/* Register values, word */
 	u8 conf;			/* Register encoding, combined */
 };
 
@@ -101,7 +101,7 @@ static struct i2c_driver ds1621_driver = {
 
 /* All registers are word-sized, except for the configuration register.
    DS1621 uses a high-byte first convention, which is exactly opposite to
-   the usual practice. */
+   the SMBus standard. */
 static int ds1621_read_value(struct i2c_client *client, u8 reg)
 {
 	if (reg == DS1621_REG_CONF)
@@ -110,9 +110,6 @@ static int ds1621_read_value(struct i2c_client *client, u8 reg)
 		return swab16(i2c_smbus_read_word_data(client, reg));
 }
 
-/* All registers are word-sized, except for the configuration register.
-   DS1621 uses a high-byte first convention, which is exactly opposite to
-   the usual practice. */
 static int ds1621_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if (reg == DS1621_REG_CONF)
@@ -139,50 +136,61 @@ static void ds1621_init_client(struct i2c_client *client)
 	i2c_smbus_write_byte(client, DS1621_COM_START);
 }
 
-#define show(value)							\
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
-{									\
-	struct ds1621_data *data = ds1621_update_client(dev);		\
-	return sprintf(buf, "%d\n", LM75_TEMP_FROM_REG(data->value));	\
+static ssize_t show_temp(struct device *dev, struct device_attribute *da,
+			 char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ds1621_data *data = ds1621_update_client(dev);
+	return sprintf(buf, "%d\n",
+		       LM75_TEMP_FROM_REG(data->temp[attr->index]));
 }
 
-show(temp);
-show(temp_min);
-show(temp_max);
-
-#define set_temp(suffix, value, reg)					\
-static ssize_t set_temp_##suffix(struct device *dev, struct device_attribute *attr, const char *buf,	\
-				 size_t count)				\
-{									\
-	struct i2c_client *client = to_i2c_client(dev);			\
-	struct ds1621_data *data = ds1621_update_client(dev);		\
-	u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10));	\
-									\
-	mutex_lock(&data->update_lock);					\
-	data->value = val;						\
-	ds1621_write_value(client, reg, data->value);			\
-	mutex_unlock(&data->update_lock);				\
-	return count;							\
-}
+static ssize_t set_temp(struct device *dev, struct device_attribute *da,
+			const char *buf, size_t count)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct i2c_client *client = to_i2c_client(dev);
+	struct ds1621_data *data = ds1621_update_client(dev);
+	u16 val = LM75_TEMP_TO_REG(simple_strtoul(buf, NULL, 10));
 
-set_temp(min, temp_min, DS1621_REG_TEMP_MIN);
-set_temp(max, temp_max, DS1621_REG_TEMP_MAX);
+	mutex_lock(&data->update_lock);
+	data->temp[attr->index] = val;
+	ds1621_write_value(client, DS1621_REG_TEMP[attr->index],
+			   data->temp[attr->index]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
 
-static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+static ssize_t show_alarms(struct device *dev, struct device_attribute *da,
+			   char *buf)
 {
 	struct ds1621_data *data = ds1621_update_client(dev);
 	return sprintf(buf, "%d\n", ALARMS_FROM_REG(data->conf));
 }
 
+static ssize_t show_alarm(struct device *dev, struct device_attribute *da,
+			  char *buf)
+{
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	struct ds1621_data *data = ds1621_update_client(dev);
+	return sprintf(buf, "%d\n", !!(data->conf & attr->index));
+}
+
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
-static DEVICE_ATTR(temp1_input, S_IRUGO , show_temp, NULL);
-static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO , show_temp_min, set_temp_min);
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp, set_temp, 1);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp, set_temp, 2);
+static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL,
+		DS1621_ALARM_TEMP_LOW);
+static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL,
+		DS1621_ALARM_TEMP_HIGH);
 
 static struct attribute *ds1621_attributes[] = {
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp1_min.attr,
-	&dev_attr_temp1_max.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
 	&dev_attr_alarms.attr,
 	NULL
 };
@@ -204,9 +212,9 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
 			 int kind)
 {
 	int conf, temp;
-	struct i2c_client *new_client;
+	struct i2c_client *client;
 	struct ds1621_data *data;
-	int err = 0;
+	int i, err = 0;
 
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA 
 				     | I2C_FUNC_SMBUS_WORD_DATA 
@@ -221,55 +229,44 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
 		goto exit;
 	}
 	
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &ds1621_driver;
-	new_client->flags = 0;
-
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &ds1621_driver;
 
 	/* Now, we do the remaining detection. It is lousy. */
 	if (kind < 0) {
 		/* The NVB bit should be low if no EEPROM write has been 
 		   requested during the latest 10ms, which is highly 
 		   improbable in our case. */
-		conf = ds1621_read_value(new_client, DS1621_REG_CONF);
+		conf = ds1621_read_value(client, DS1621_REG_CONF);
 		if (conf & DS1621_REG_CONFIG_NVB)
 			goto exit_free;
 		/* The 7 lowest bits of a temperature should always be 0. */
-		temp = ds1621_read_value(new_client, DS1621_REG_TEMP);
-		if (temp & 0x007f)
-			goto exit_free;
-		temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MIN);
-		if (temp & 0x007f)
-			goto exit_free;
-		temp = ds1621_read_value(new_client, DS1621_REG_TEMP_MAX);
-		if (temp & 0x007f)
-			goto exit_free;
+		for (i = 0; i < ARRAY_SIZE(data->temp); i++) {
+			temp = ds1621_read_value(client, DS1621_REG_TEMP[i]);
+			if (temp & 0x007f)
+				goto exit_free;
+		}
 	}
 
-	/* Determine the chip type - only one kind supported! */
-	if (kind <= 0)
-		kind = ds1621;
-
 	/* Fill in remaining client fields and put it into the global list */
-	strlcpy(new_client->name, "ds1621", I2C_NAME_SIZE);
-	data->valid = 0;
+	strlcpy(client->name, "ds1621", I2C_NAME_SIZE);
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
+	if ((err = i2c_attach_client(client)))
 		goto exit_free;
 
 	/* Initialize the DS1621 chip */
-	ds1621_init_client(new_client);
+	ds1621_init_client(client);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &ds1621_group)))
+	if ((err = sysfs_create_group(&client->dev.kobj, &ds1621_group)))
 		goto exit_detach;
 
-	data->class_dev = hwmon_device_register(&new_client->dev);
+	data->class_dev = hwmon_device_register(&client->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto exit_remove_files;
@@ -278,9 +275,9 @@ static int ds1621_detect(struct i2c_adapter *adapter, int address,
 	return 0;
 
       exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &ds1621_group);
+	sysfs_remove_group(&client->dev.kobj, &ds1621_group);
       exit_detach:
-	i2c_detach_client(new_client);
+	i2c_detach_client(client);
       exit_free:
 	kfree(data);
       exit:
@@ -314,23 +311,21 @@ static struct ds1621_data *ds1621_update_client(struct device *dev)
 
 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 	    || !data->valid) {
+		int i;
 
 		dev_dbg(&client->dev, "Starting ds1621 update\n");
 
 		data->conf = ds1621_read_value(client, DS1621_REG_CONF);
 
-		data->temp = ds1621_read_value(client, DS1621_REG_TEMP);
-		
-		data->temp_min = ds1621_read_value(client,
-		                                    DS1621_REG_TEMP_MIN);
-		data->temp_max = ds1621_read_value(client,
-						    DS1621_REG_TEMP_MAX);
+		for (i = 0; i < ARRAY_SIZE(data->temp); i++)
+			data->temp[i] = ds1621_read_value(client,
+							  DS1621_REG_TEMP[i]);
 
 		/* reset alarms if necessary */
 		new_conf = data->conf;
-		if (data->temp > data->temp_min)
+		if (data->temp[0] > data->temp[1])	/* input > min */
 			new_conf &= ~DS1621_ALARM_TEMP_LOW;
-		if (data->temp < data->temp_max)
+		if (data->temp[0] < data->temp[2])	/* input < max */
 			new_conf &= ~DS1621_ALARM_TEMP_HIGH;
 		if (data->conf != new_conf)
 			ds1621_write_value(client, DS1621_REG_CONF,
diff --git a/drivers/hwmon/f71805f.c b/drivers/hwmon/f71805f.c
index cdbe309b8fc4..6f60715f34f8 100644
--- a/drivers/hwmon/f71805f.c
+++ b/drivers/hwmon/f71805f.c
@@ -127,6 +127,13 @@ superio_exit(int base)
 #define F71805F_REG_TEMP_HIGH(nr)	(0x54 + 2 * (nr))
 #define F71805F_REG_TEMP_HYST(nr)	(0x55 + 2 * (nr))
 #define F71805F_REG_TEMP_MODE		0x01
+/* pwm/fan pwmnr from 0 to 2, auto point apnr from 0 to 2 */
+/* map Fintek numbers to our numbers as follows: 9->0, 5->1, 1->2 */
+#define F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr) \
+					(0xA0 + 0x10 * (pwmnr) + (2 - (apnr)))
+#define F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr) \
+					(0xA4 + 0x10 * (pwmnr) + \
+						2 * (2 - (apnr)))
 
 #define F71805F_REG_START		0x00
 /* status nr from 0 to 2 */
@@ -144,6 +151,11 @@ superio_exit(int base)
  * Data structures and manipulation thereof
  */
 
+struct f71805f_auto_point {
+	u8 temp[3];
+	u16 fan[3];
+};
+
 struct f71805f_data {
 	unsigned short addr;
 	const char *name;
@@ -170,6 +182,7 @@ struct f71805f_data {
 	u8 temp_hyst[3];
 	u8 temp_mode;
 	unsigned long alarms;
+	struct f71805f_auto_point auto_points[3];
 };
 
 struct f71805f_sio_data {
@@ -312,7 +325,7 @@ static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
 static struct f71805f_data *f71805f_update_device(struct device *dev)
 {
 	struct f71805f_data *data = dev_get_drvdata(dev);
-	int nr;
+	int nr, apnr;
 
 	mutex_lock(&data->update_lock);
 
@@ -342,6 +355,18 @@ static struct f71805f_data *f71805f_update_device(struct device *dev)
 					      F71805F_REG_TEMP_HYST(nr));
 		}
 		data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
+		for (nr = 0; nr < 3; nr++) {
+			for (apnr = 0; apnr < 3; apnr++) {
+				data->auto_points[nr].temp[apnr] =
+					f71805f_read8(data,
+					F71805F_REG_PWM_AUTO_POINT_TEMP(nr,
+									apnr));
+				data->auto_points[nr].fan[apnr] =
+					f71805f_read16(data,
+					F71805F_REG_PWM_AUTO_POINT_FAN(nr,
+								       apnr));
+			}
+		}
 
 		data->last_limits = jiffies;
 	}
@@ -705,6 +730,70 @@ static ssize_t set_pwm_freq(struct device *dev, struct device_attribute
 	return count;
 }
 
+static ssize_t show_pwm_auto_point_temp(struct device *dev,
+					struct device_attribute *devattr,
+					char* buf)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	int pwmnr = attr->nr;
+	int apnr = attr->index;
+
+	return sprintf(buf, "%ld\n",
+		       temp_from_reg(data->auto_points[pwmnr].temp[apnr]));
+}
+
+static ssize_t set_pwm_auto_point_temp(struct device *dev,
+				       struct device_attribute *devattr,
+				       const char* buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	int pwmnr = attr->nr;
+	int apnr = attr->index;
+	unsigned long val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->auto_points[pwmnr].temp[apnr] = temp_to_reg(val);
+	f71805f_write8(data, F71805F_REG_PWM_AUTO_POINT_TEMP(pwmnr, apnr),
+		       data->auto_points[pwmnr].temp[apnr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t show_pwm_auto_point_fan(struct device *dev,
+				       struct device_attribute *devattr,
+				       char* buf)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	int pwmnr = attr->nr;
+	int apnr = attr->index;
+
+	return sprintf(buf, "%ld\n",
+		       fan_from_reg(data->auto_points[pwmnr].fan[apnr]));
+}
+
+static ssize_t set_pwm_auto_point_fan(struct device *dev,
+				      struct device_attribute *devattr,
+				      const char* buf, size_t count)
+{
+	struct f71805f_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute_2 *attr = to_sensor_dev_attr_2(devattr);
+	int pwmnr = attr->nr;
+	int apnr = attr->index;
+	unsigned long val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->auto_points[pwmnr].fan[apnr] = fan_to_reg(val);
+	f71805f_write16(data, F71805F_REG_PWM_AUTO_POINT_FAN(pwmnr, apnr),
+		        data->auto_points[pwmnr].fan[apnr]);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
 static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
 			 char *buf)
 {
@@ -932,6 +1021,63 @@ static SENSOR_DEVICE_ATTR(pwm3_freq, S_IRUGO | S_IWUSR,
 			  show_pwm_freq, set_pwm_freq, 2);
 static SENSOR_DEVICE_ATTR(pwm3_mode, S_IRUGO, show_pwm_mode, NULL, 2);
 
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point1_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    0, 0);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point2_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    0, 1);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    0, 2);
+static SENSOR_DEVICE_ATTR_2(pwm1_auto_point3_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    0, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point1_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    1, 0);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point2_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    1, 1);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    1, 2);
+static SENSOR_DEVICE_ATTR_2(pwm2_auto_point3_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    1, 2);
+
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point1_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    2, 0);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point2_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    2, 1);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_temp, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_temp, set_pwm_auto_point_temp,
+			    2, 2);
+static SENSOR_DEVICE_ATTR_2(pwm3_auto_point3_fan, S_IRUGO | S_IWUSR,
+			    show_pwm_auto_point_fan, set_pwm_auto_point_fan,
+			    2, 2);
+
 static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0);
 static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 1);
 static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 2);
@@ -1014,6 +1160,25 @@ static struct attribute *f71805f_attributes[] = {
 	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
 	&sensor_dev_attr_temp3_type.dev_attr.attr,
 
+	&sensor_dev_attr_pwm1_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point1_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point2_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_point3_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point1_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point2_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_point3_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point1_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point1_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point2_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point2_fan.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point3_temp.dev_attr.attr,
+	&sensor_dev_attr_pwm3_auto_point3_fan.dev_attr.attr,
+
 	&sensor_dev_attr_in0_alarm.dev_attr.attr,
 	&sensor_dev_attr_in1_alarm.dev_attr.attr,
 	&sensor_dev_attr_in2_alarm.dev_attr.attr,
@@ -1242,12 +1407,12 @@ static int __devexit f71805f_remove(struct platform_device *pdev)
 	struct resource *res;
 	int i;
 
-	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group);
 	for (i = 0; i < 4; i++)
 		sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_optin[i]);
 	sysfs_remove_group(&pdev->dev.kobj, &f71805f_group_pwm_freq);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1290,15 +1455,12 @@ static int __init f71805f_device_add(unsigned short address,
 		goto exit_device_put;
 	}
 
-	pdev->dev.platform_data = kmalloc(sizeof(struct f71805f_sio_data),
-					  GFP_KERNEL);
-	if (!pdev->dev.platform_data) {
-		err = -ENOMEM;
+	err = platform_device_add_data(pdev, sio_data,
+				       sizeof(struct f71805f_sio_data));
+	if (err) {
 		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
 		goto exit_device_put;
 	}
-	memcpy(pdev->dev.platform_data, sio_data,
-	       sizeof(struct f71805f_sio_data));
 
 	err = platform_device_add(pdev);
 	if (err) {
diff --git a/drivers/hwmon/fscher.c b/drivers/hwmon/fscher.c
index 19717752cfca..b34b546c68b8 100644
--- a/drivers/hwmon/fscher.c
+++ b/drivers/hwmon/fscher.c
@@ -441,6 +441,8 @@ static struct fscher_data *fscher_update_device(struct device *dev)
 		data->watchdog[2] = fscher_read_value(client, FSCHER_REG_WDOG_CONTROL);
 
 		data->global_event = fscher_read_value(client, FSCHER_REG_EVENT_STATE);
+		data->global_control = fscher_read_value(client,
+							FSCHER_REG_CONTROL);
 
 		data->last_updated = jiffies;
 		data->valid = 1;                 
@@ -599,7 +601,7 @@ static ssize_t set_control(struct i2c_client *client, struct fscher_data *data,
 	unsigned long v = simple_strtoul(buf, NULL, 10) & 0x01;
 
 	mutex_lock(&data->update_lock);
-	data->global_control &= ~v;
+	data->global_control = v;
 	fscher_write_value(client, reg, v);
 	mutex_unlock(&data->update_lock);
 	return count;
diff --git a/drivers/hwmon/hdaps.c b/drivers/hwmon/hdaps.c
index e0cf5e6fe5bc..a7c6d407572b 100644
--- a/drivers/hwmon/hdaps.c
+++ b/drivers/hwmon/hdaps.c
@@ -480,14 +480,14 @@ static struct attribute_group hdaps_attribute_group = {
 /* Module stuff */
 
 /* hdaps_dmi_match - found a match.  return one, short-circuiting the hunt. */
-static int __init hdaps_dmi_match(struct dmi_system_id *id)
+static int __init hdaps_dmi_match(const struct dmi_system_id *id)
 {
 	printk(KERN_INFO "hdaps: %s detected.\n", id->ident);
 	return 1;
 }
 
 /* hdaps_dmi_match_invert - found an inverted match. */
-static int __init hdaps_dmi_match_invert(struct dmi_system_id *id)
+static int __init hdaps_dmi_match_invert(const struct dmi_system_id *id)
 {
 	hdaps_invert = 1;
 	printk(KERN_INFO "hdaps: inverting axis readings.\n");
diff --git a/drivers/hwmon/it87.c b/drivers/hwmon/it87.c
index 62afc63708a5..d75dba9b810b 100644
--- a/drivers/hwmon/it87.c
+++ b/drivers/hwmon/it87.c
@@ -6,6 +6,7 @@
               IT8712F  Super I/O chip w/LPC interface
               IT8716F  Super I/O chip w/LPC interface
               IT8718F  Super I/O chip w/LPC interface
+              IT8726F  Super I/O chip w/LPC interface
               Sis950   A clone of the IT8705F
 
     Copyright (C) 2001 Chris Gauthron <chrisg@0-in.com> 
@@ -30,8 +31,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
@@ -40,10 +40,12 @@
 #include <linux/sysfs.h>
 #include <asm/io.h>
 
+#define DRVNAME "it87"
 
-static unsigned short isa_address;
 enum chips { it87, it8712, it8716, it8718 };
 
+static struct platform_device *pdev;
+
 #define	REG	0x2e	/* The register to read/write */
 #define	DEV	0x07	/* Register: Logical device select */
 #define	VAL	0x2f	/* The value to read/write */
@@ -97,6 +99,7 @@ superio_exit(void)
 #define IT8705F_DEVID 0x8705
 #define IT8716F_DEVID 0x8716
 #define IT8718F_DEVID 0x8718
+#define IT8726F_DEVID 0x8726
 #define IT87_ACT_REG  0x30
 #define IT87_BASE_REG 0x60
 
@@ -110,10 +113,6 @@ static int update_vbat;
 /* Not all BIOSes properly configure the PWM registers */
 static int fix_pwm_polarity;
 
-/* Values read from Super-I/O config space */
-static u16 chip_type;
-static u8 vid_value;
-
 /* Many IT87 constants specified below */
 
 /* Length of ISA address segment */
@@ -214,13 +213,20 @@ static const unsigned int pwm_freq[8] = {
 };
 
 
+struct it87_sio_data {
+	enum chips type;
+	/* Values read from Super-I/O config space */
+	u8 vid_value;
+};
+
 /* For each registered chip, we need to keep some data in memory.
    The structure is dynamically allocated. */
 struct it87_data {
-	struct i2c_client client;
 	struct class_device *class_dev;
 	enum chips type;
 
+	unsigned short addr;
+	const char *name;
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -245,26 +251,25 @@ struct it87_data {
 };
 
 
-static int it87_detect(struct i2c_adapter *adapter);
-static int it87_detach_client(struct i2c_client *client);
+static int it87_probe(struct platform_device *pdev);
+static int __devexit it87_remove(struct platform_device *pdev);
 
-static int it87_read_value(struct i2c_client *client, u8 reg);
-static void it87_write_value(struct i2c_client *client, u8 reg, u8 value);
+static int it87_read_value(struct it87_data *data, u8 reg);
+static void it87_write_value(struct it87_data *data, u8 reg, u8 value);
 static struct it87_data *it87_update_device(struct device *dev);
-static int it87_check_pwm(struct i2c_client *client);
-static void it87_init_client(struct i2c_client *client, struct it87_data *data);
+static int it87_check_pwm(struct device *dev);
+static void it87_init_device(struct platform_device *pdev);
 
 
-static struct i2c_driver it87_isa_driver = {
+static struct platform_driver it87_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
-		.name	= "it87-isa",
+		.name	= DRVNAME,
 	},
-	.attach_adapter	= it87_detect,
-	.detach_client	= it87_detach_client,
+	.probe	= it87_probe,
+	.remove	= __devexit_p(it87_remove),
 };
 
-
 static ssize_t show_in(struct device *dev, struct device_attribute *attr,
 		char *buf)
 {
@@ -301,13 +306,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val);
-	it87_write_value(client, IT87_REG_VIN_MIN(nr), 
+	it87_write_value(data, IT87_REG_VIN_MIN(nr),
 			data->in_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -318,13 +322,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val);
-	it87_write_value(client, IT87_REG_VIN_MAX(nr), 
+	it87_write_value(data, IT87_REG_VIN_MAX(nr),
 			data->in_max[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -392,13 +395,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_high[nr] = TEMP_TO_REG(val);
-	it87_write_value(client, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
+	it87_write_value(data, IT87_REG_TEMP_HIGH(nr), data->temp_high[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -408,13 +410,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_low[nr] = TEMP_TO_REG(val);
-	it87_write_value(client, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
+	it87_write_value(data, IT87_REG_TEMP_LOW(nr), data->temp_low[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -451,8 +452,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -468,7 +468,7 @@ static ssize_t set_sensor(struct device *dev, struct device_attribute *attr,
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
 	}
-	it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor);
+	it87_write_value(data, IT87_REG_TEMP_ENABLE, data->sensor);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -542,13 +542,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 	u8 reg;
 
 	mutex_lock(&data->update_lock);
-	reg = it87_read_value(client, IT87_REG_FAN_DIV);
+	reg = it87_read_value(data, IT87_REG_FAN_DIV);
 	switch (nr) {
 	case 0: data->fan_div[nr] = reg & 0x07; break;
 	case 1: data->fan_div[nr] = (reg >> 3) & 0x07; break;
@@ -556,7 +555,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 	}
 
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-	it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
+	it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -566,14 +565,13 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int min;
 	u8 old;
 
 	mutex_lock(&data->update_lock);
-	old = it87_read_value(client, IT87_REG_FAN_DIV);
+	old = it87_read_value(data, IT87_REG_FAN_DIV);
 
 	/* Save fan min limit */
 	min = FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr]));
@@ -594,11 +592,11 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	val |= (data->fan_div[1] & 0x07) << 3;
 	if (data->fan_div[2] == 3)
 		val |= 0x1 << 6;
-	it87_write_value(client, IT87_REG_FAN_DIV, val);
+	it87_write_value(data, IT87_REG_FAN_DIV, val);
 
 	/* Restore fan min limit */
 	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-	it87_write_value(client, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
+	it87_write_value(data, IT87_REG_FAN_MIN(nr), data->fan_min[nr]);
 
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -609,8 +607,7 @@ static ssize_t set_pwm_enable(struct device *dev,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -618,17 +615,17 @@ static ssize_t set_pwm_enable(struct device *dev,
 	if (val == 0) {
 		int tmp;
 		/* make sure the fan is on when in on/off mode */
-		tmp = it87_read_value(client, IT87_REG_FAN_CTL);
-		it87_write_value(client, IT87_REG_FAN_CTL, tmp | (1 << nr));
+		tmp = it87_read_value(data, IT87_REG_FAN_CTL);
+		it87_write_value(data, IT87_REG_FAN_CTL, tmp | (1 << nr));
 		/* set on/off mode */
 		data->fan_main_ctrl &= ~(1 << nr);
-		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
 	} else if (val == 1) {
 		/* set SmartGuardian mode */
 		data->fan_main_ctrl |= (1 << nr);
-		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
 		/* set saved pwm value, clear FAN_CTLX PWM mode bit */
-		it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
+		it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
 	} else {
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
@@ -643,8 +640,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	if (val < 0 || val > 255)
@@ -653,15 +649,14 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *attr,
 	mutex_lock(&data->update_lock);
 	data->manual_pwm_ctl[nr] = val;
 	if (data->fan_main_ctrl & (1 << nr))
-		it87_write_value(client, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
+		it87_write_value(data, IT87_REG_PWM(nr), PWM_TO_REG(data->manual_pwm_ctl[nr]));
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 static ssize_t set_pwm_freq(struct device *dev,
 		struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int i;
 
@@ -672,9 +667,9 @@ static ssize_t set_pwm_freq(struct device *dev,
 	}
 
 	mutex_lock(&data->update_lock);
-	data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL) & 0x8f;
+	data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL) & 0x8f;
 	data->fan_ctl |= i << 4;
-	it87_write_value(client, IT87_REG_FAN_CTL, data->fan_ctl);
+	it87_write_value(data, IT87_REG_FAN_CTL, data->fan_ctl);
 	mutex_unlock(&data->update_lock);
 
 	return count;
@@ -729,15 +724,14 @@ static ssize_t set_fan16_min(struct device *dev, struct device_attribute *attr,
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN16_TO_REG(val);
-	it87_write_value(client, IT87_REG_FAN_MIN(nr),
+	it87_write_value(data, IT87_REG_FAN_MIN(nr),
 			 data->fan_min[nr] & 0xff);
-	it87_write_value(client, IT87_REG_FANX_MIN(nr),
+	it87_write_value(data, IT87_REG_FANX_MIN(nr),
 			 data->fan_min[nr] >> 8);
 	mutex_unlock(&data->update_lock);
 	return count;
@@ -775,8 +769,7 @@ show_vrm_reg(struct device *dev, struct device_attribute *attr, char *buf)
 static ssize_t
 store_vrm_reg(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	u32 val;
 
 	val = simple_strtoul(buf, NULL, 10);
@@ -794,6 +787,14 @@ show_vid_reg(struct device *dev, struct device_attribute *attr, char *buf)
 }
 static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid_reg, NULL);
 
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct it87_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 static struct attribute *it87_attributes[] = {
 	&sensor_dev_attr_in0_input.dev_attr.attr,
 	&sensor_dev_attr_in1_input.dev_attr.attr,
@@ -835,6 +836,7 @@ static struct attribute *it87_attributes[] = {
 	&sensor_dev_attr_temp3_type.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
+	&dev_attr_name.attr,
 	NULL
 };
 
@@ -877,17 +879,36 @@ static const struct attribute_group it87_group_opt = {
 };
 
 /* SuperIO detection - will change isa_address if a chip is found */
-static int __init it87_find(unsigned short *address)
+static int __init it87_find(unsigned short *address,
+	struct it87_sio_data *sio_data)
 {
 	int err = -ENODEV;
+	u16 chip_type;
 
 	superio_enter();
 	chip_type = superio_inw(DEVID);
-	if (chip_type != IT8712F_DEVID
-	 && chip_type != IT8716F_DEVID
-	 && chip_type != IT8718F_DEVID
-	 && chip_type != IT8705F_DEVID)
-	 	goto exit;
+
+	switch (chip_type) {
+	case IT8705F_DEVID:
+		sio_data->type = it87;
+		break;
+	case IT8712F_DEVID:
+		sio_data->type = it8712;
+		break;
+	case IT8716F_DEVID:
+	case IT8726F_DEVID:
+		sio_data->type = it8716;
+		break;
+	case IT8718F_DEVID:
+		sio_data->type = it8718;
+		break;
+	case 0xffff:	/* No device at all */
+		goto exit;
+	default:
+		pr_debug(DRVNAME ": Unsupported chip (DEVID=0x%x)\n",
+			 chip_type);
+		goto exit;
+	}
 
 	superio_select(PME);
 	if (!(superio_inb(IT87_ACT_REG) & 0x01)) {
@@ -911,7 +932,7 @@ static int __init it87_find(unsigned short *address)
 
 		superio_select(GPIO);
 		if (chip_type == it8718)
-			vid_value = superio_inb(IT87_SIO_VID_REG);
+			sio_data->vid_value = superio_inb(IT87_SIO_VID_REG);
 
 		reg = superio_inb(IT87_SIO_PINX2_REG);
 		if (reg & (1 << 0))
@@ -925,18 +946,26 @@ exit:
 	return err;
 }
 
-/* This function is called by i2c_probe */
-static int it87_detect(struct i2c_adapter *adapter)
+static int __devinit it87_probe(struct platform_device *pdev)
 {
-	struct i2c_client *new_client;
 	struct it87_data *data;
+	struct resource *res;
+	struct device *dev = &pdev->dev;
+	struct it87_sio_data *sio_data = dev->platform_data;
 	int err = 0;
-	const char *name;
 	int enable_pwm_interface;
-
-	/* Reserve the ISA region */
-	if (!request_region(isa_address, IT87_EXTENT,
-			    it87_isa_driver.driver.name)){
+	static const char *names[] = {
+		"it87",
+		"it8712",
+		"it8716",
+		"it8718",
+	};
+
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start, IT87_EXTENT, DRVNAME)) {
+		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
+			(unsigned long)res->start,
+			(unsigned long)(res->start + IT87_EXTENT - 1));
 		err = -EBUSY;
 		goto ERROR0;
 	}
@@ -946,129 +975,104 @@ static int it87_detect(struct i2c_adapter *adapter)
 		goto ERROR1;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = isa_address;
-	new_client->adapter = adapter;
-	new_client->driver = &it87_isa_driver;
+	data->addr = res->start;
+	data->type = sio_data->type;
+	data->name = names[sio_data->type];
 
 	/* Now, we do the remaining detection. */
-	if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
-	 || it87_read_value(new_client, IT87_REG_CHIPID) != 0x90) {
+	if ((it87_read_value(data, IT87_REG_CONFIG) & 0x80)
+	 || it87_read_value(data, IT87_REG_CHIPID) != 0x90) {
 		err = -ENODEV;
 		goto ERROR2;
 	}
 
-	/* Determine the chip type. */
-	switch (chip_type) {
-	case IT8712F_DEVID:
-		data->type = it8712;
-		name = "it8712";
-		break;
-	case IT8716F_DEVID:
-		data->type = it8716;
-		name = "it8716";
-		break;
-	case IT8718F_DEVID:
-		data->type = it8718;
-		name = "it8718";
-		break;
-	default:
-		data->type = it87;
-		name = "it87";
-	}
+	platform_set_drvdata(pdev, data);
 
-	/* Fill in the remaining client fields and put it into the global list */
-	strlcpy(new_client->name, name, I2C_NAME_SIZE);
 	mutex_init(&data->update_lock);
 
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
-		goto ERROR2;
-
 	/* Check PWM configuration */
-	enable_pwm_interface = it87_check_pwm(new_client);
+	enable_pwm_interface = it87_check_pwm(dev);
 
 	/* Initialize the IT87 chip */
-	it87_init_client(new_client, data);
+	it87_init_device(pdev);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &it87_group)))
-		goto ERROR3;
+	if ((err = sysfs_create_group(&dev->kobj, &it87_group)))
+		goto ERROR2;
 
 	/* Do not create fan files for disabled fans */
 	if (data->type == it8716 || data->type == it8718) {
 		/* 16-bit tachometers */
 		if (data->has_fan & (1 << 0)) {
-			if ((err = device_create_file(&new_client->dev,
+			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_input16.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_min16.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 1)) {
-			if ((err = device_create_file(&new_client->dev,
+			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_input16.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_min16.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 2)) {
-			if ((err = device_create_file(&new_client->dev,
+			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_input16.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_min16.dev_attr)))
 				goto ERROR4;
 		}
 	} else {
 		/* 8-bit tachometers with clock divider */
 		if (data->has_fan & (1 << 0)) {
-			if ((err = device_create_file(&new_client->dev,
+			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_input.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_min.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan1_div.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 1)) {
-			if ((err = device_create_file(&new_client->dev,
+			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_input.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_min.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan2_div.dev_attr)))
 				goto ERROR4;
 		}
 		if (data->has_fan & (1 << 2)) {
-			if ((err = device_create_file(&new_client->dev,
+			if ((err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_input.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_min.dev_attr))
-			 || (err = device_create_file(&new_client->dev,
+			 || (err = device_create_file(dev,
 			     &sensor_dev_attr_fan3_div.dev_attr)))
 				goto ERROR4;
 		}
 	}
 
 	if (enable_pwm_interface) {
-		if ((err = device_create_file(&new_client->dev,
+		if ((err = device_create_file(dev,
 		     &sensor_dev_attr_pwm1_enable.dev_attr))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &sensor_dev_attr_pwm2_enable.dev_attr))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &sensor_dev_attr_pwm3_enable.dev_attr))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &sensor_dev_attr_pwm1.dev_attr))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &sensor_dev_attr_pwm2.dev_attr))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &sensor_dev_attr_pwm3.dev_attr))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &dev_attr_pwm1_freq))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &dev_attr_pwm2_freq))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &dev_attr_pwm3_freq)))
 			goto ERROR4;
 	}
@@ -1077,15 +1081,15 @@ static int it87_detect(struct i2c_adapter *adapter)
 	 || data->type == it8718) {
 		data->vrm = vid_which_vrm();
 		/* VID reading from Super-I/O config space if available */
-		data->vid = vid_value;
-		if ((err = device_create_file(&new_client->dev,
+		data->vid = sio_data->vid_value;
+		if ((err = device_create_file(dev,
 		     &dev_attr_vrm))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(dev,
 		     &dev_attr_cpu0_vid)))
 			goto ERROR4;
 	}
 
-	data->class_dev = hwmon_device_register(&new_client->dev);
+	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto ERROR4;
@@ -1094,31 +1098,27 @@ static int it87_detect(struct i2c_adapter *adapter)
 	return 0;
 
 ERROR4:
-	sysfs_remove_group(&new_client->dev.kobj, &it87_group);
-	sysfs_remove_group(&new_client->dev.kobj, &it87_group_opt);
-ERROR3:
-	i2c_detach_client(new_client);
+	sysfs_remove_group(&dev->kobj, &it87_group);
+	sysfs_remove_group(&dev->kobj, &it87_group_opt);
 ERROR2:
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 ERROR1:
-	release_region(isa_address, IT87_EXTENT);
+	release_region(res->start, IT87_EXTENT);
 ERROR0:
 	return err;
 }
 
-static int it87_detach_client(struct i2c_client *client)
+static int __devexit it87_remove(struct platform_device *pdev)
 {
-	struct it87_data *data = i2c_get_clientdata(client);
-	int err;
+	struct it87_data *data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(data->class_dev);
-	sysfs_remove_group(&client->dev.kobj, &it87_group);
-	sysfs_remove_group(&client->dev.kobj, &it87_group_opt);
+	sysfs_remove_group(&pdev->dev.kobj, &it87_group);
+	sysfs_remove_group(&pdev->dev.kobj, &it87_group_opt);
 
-	if ((err = i2c_detach_client(client)))
-		return err;
-
-	release_region(client->addr, IT87_EXTENT);
+	release_region(data->addr, IT87_EXTENT);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
@@ -1127,28 +1127,29 @@ static int it87_detach_client(struct i2c_client *client)
 /* Must be called with data->update_lock held, except during initialization.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the IT87 access and should not be necessary. */
-static int it87_read_value(struct i2c_client *client, u8 reg)
+static int it87_read_value(struct it87_data *data, u8 reg)
 {
-	outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
-	return inb_p(client->addr + IT87_DATA_REG_OFFSET);
+	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
+	return inb_p(data->addr + IT87_DATA_REG_OFFSET);
 }
 
 /* Must be called with data->update_lock held, except during initialization.
    We ignore the IT87 BUSY flag at this moment - it could lead to deadlocks,
    would slow down the IT87 access and should not be necessary. */
-static void it87_write_value(struct i2c_client *client, u8 reg, u8 value)
+static void it87_write_value(struct it87_data *data, u8 reg, u8 value)
 {
-	outb_p(reg, client->addr + IT87_ADDR_REG_OFFSET);
-	outb_p(value, client->addr + IT87_DATA_REG_OFFSET);
+	outb_p(reg, data->addr + IT87_ADDR_REG_OFFSET);
+	outb_p(value, data->addr + IT87_DATA_REG_OFFSET);
 }
 
 /* Return 1 if and only if the PWM interface is safe to use */
-static int it87_check_pwm(struct i2c_client *client)
+static int __devinit it87_check_pwm(struct device *dev)
 {
+	struct it87_data *data = dev_get_drvdata(dev);
 	/* Some BIOSes fail to correctly configure the IT87 fans. All fans off
 	 * and polarity set to active low is sign that this is the case so we
 	 * disable pwm control to protect the user. */
-	int tmp = it87_read_value(client, IT87_REG_FAN_CTL);
+	int tmp = it87_read_value(data, IT87_REG_FAN_CTL);
 	if ((tmp & 0x87) == 0) {
 		if (fix_pwm_polarity) {
 			/* The user asks us to attempt a chip reconfiguration.
@@ -1158,7 +1159,7 @@ static int it87_check_pwm(struct i2c_client *client)
 			u8 pwm[3];
 
 			for (i = 0; i < 3; i++)
-				pwm[i] = it87_read_value(client,
+				pwm[i] = it87_read_value(data,
 							 IT87_REG_PWM(i));
 
 			/* If any fan is in automatic pwm mode, the polarity
@@ -1166,26 +1167,26 @@ static int it87_check_pwm(struct i2c_client *client)
 			 * better don't change anything (but still disable the
 			 * PWM interface). */
 			if (!((pwm[0] | pwm[1] | pwm[2]) & 0x80)) {
-				dev_info(&client->dev, "Reconfiguring PWM to "
+				dev_info(dev, "Reconfiguring PWM to "
 					 "active high polarity\n");
-				it87_write_value(client, IT87_REG_FAN_CTL,
+				it87_write_value(data, IT87_REG_FAN_CTL,
 						 tmp | 0x87);
 				for (i = 0; i < 3; i++)
-					it87_write_value(client,
+					it87_write_value(data,
 							 IT87_REG_PWM(i),
 							 0x7f & ~pwm[i]);
 				return 1;
 			}
 
-			dev_info(&client->dev, "PWM configuration is "
+			dev_info(dev, "PWM configuration is "
 				 "too broken to be fixed\n");
 		}
 
-		dev_info(&client->dev, "Detected broken BIOS "
+		dev_info(dev, "Detected broken BIOS "
 			 "defaults, disabling PWM interface\n");
 		return 0;
 	} else if (fix_pwm_polarity) {
-		dev_info(&client->dev, "PWM configuration looks "
+		dev_info(dev, "PWM configuration looks "
 			 "sane, won't touch\n");
 	}
 
@@ -1193,8 +1194,9 @@ static int it87_check_pwm(struct i2c_client *client)
 }
 
 /* Called when we have found a new IT87. */
-static void it87_init_client(struct i2c_client *client, struct it87_data *data)
+static void __devinit it87_init_device(struct platform_device *pdev)
 {
+	struct it87_data *data = platform_get_drvdata(pdev);
 	int tmp, i;
 
 	/* initialize to sane defaults:
@@ -1214,48 +1216,48 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data)
 	 * means -1 degree C, which surprisingly doesn't trigger an alarm,
 	 * but is still confusing, so change to 127 degrees C. */
 	for (i = 0; i < 8; i++) {
-		tmp = it87_read_value(client, IT87_REG_VIN_MIN(i));
+		tmp = it87_read_value(data, IT87_REG_VIN_MIN(i));
 		if (tmp == 0xff)
-			it87_write_value(client, IT87_REG_VIN_MIN(i), 0);
+			it87_write_value(data, IT87_REG_VIN_MIN(i), 0);
 	}
 	for (i = 0; i < 3; i++) {
-		tmp = it87_read_value(client, IT87_REG_TEMP_HIGH(i));
+		tmp = it87_read_value(data, IT87_REG_TEMP_HIGH(i));
 		if (tmp == 0xff)
-			it87_write_value(client, IT87_REG_TEMP_HIGH(i), 127);
+			it87_write_value(data, IT87_REG_TEMP_HIGH(i), 127);
 	}
 
 	/* Check if temperature channnels are reset manually or by some reason */
-	tmp = it87_read_value(client, IT87_REG_TEMP_ENABLE);
+	tmp = it87_read_value(data, IT87_REG_TEMP_ENABLE);
 	if ((tmp & 0x3f) == 0) {
 		/* Temp1,Temp3=thermistor; Temp2=thermal diode */
 		tmp = (tmp & 0xc0) | 0x2a;
-		it87_write_value(client, IT87_REG_TEMP_ENABLE, tmp);
+		it87_write_value(data, IT87_REG_TEMP_ENABLE, tmp);
 	}
 	data->sensor = tmp;
 
 	/* Check if voltage monitors are reset manually or by some reason */
-	tmp = it87_read_value(client, IT87_REG_VIN_ENABLE);
+	tmp = it87_read_value(data, IT87_REG_VIN_ENABLE);
 	if ((tmp & 0xff) == 0) {
 		/* Enable all voltage monitors */
-		it87_write_value(client, IT87_REG_VIN_ENABLE, 0xff);
+		it87_write_value(data, IT87_REG_VIN_ENABLE, 0xff);
 	}
 
 	/* Check if tachometers are reset manually or by some reason */
-	data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL);
+	data->fan_main_ctrl = it87_read_value(data, IT87_REG_FAN_MAIN_CTRL);
 	if ((data->fan_main_ctrl & 0x70) == 0) {
 		/* Enable all fan tachometers */
 		data->fan_main_ctrl |= 0x70;
-		it87_write_value(client, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
+		it87_write_value(data, IT87_REG_FAN_MAIN_CTRL, data->fan_main_ctrl);
 	}
 	data->has_fan = (data->fan_main_ctrl >> 4) & 0x07;
 
 	/* Set tachometers to 16-bit mode if needed */
 	if (data->type == it8716 || data->type == it8718) {
-		tmp = it87_read_value(client, IT87_REG_FAN_16BIT);
+		tmp = it87_read_value(data, IT87_REG_FAN_16BIT);
 		if (~tmp & 0x07 & data->has_fan) {
-			dev_dbg(&client->dev,
+			dev_dbg(&pdev->dev,
 				"Setting fan1-3 to 16-bit mode\n");
-			it87_write_value(client, IT87_REG_FAN_16BIT,
+			it87_write_value(data, IT87_REG_FAN_16BIT,
 					 tmp | 0x07);
 		}
 	}
@@ -1265,7 +1267,7 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data)
 	for (i = 0; i < 3; i++) {
 		if (data->fan_main_ctrl & (1 << i)) {
 			/* pwm mode */
-			tmp = it87_read_value(client, IT87_REG_PWM(i));
+			tmp = it87_read_value(data, IT87_REG_PWM(i));
 			if (tmp & 0x80) {
 				/* automatic pwm - not yet implemented, but
 				 * leave the settings made by the BIOS alone
@@ -1279,15 +1281,14 @@ static void it87_init_client(struct i2c_client *client, struct it87_data *data)
  	}
 
 	/* Start monitoring */
-	it87_write_value(client, IT87_REG_CONFIG,
-			 (it87_read_value(client, IT87_REG_CONFIG) & 0x36)
+	it87_write_value(data, IT87_REG_CONFIG,
+			 (it87_read_value(data, IT87_REG_CONFIG) & 0x36)
 			 | (update_vbat ? 0x41 : 0x01));
 }
 
 static struct it87_data *it87_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct it87_data *data = i2c_get_clientdata(client);
+	struct it87_data *data = dev_get_drvdata(dev);
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -1298,20 +1299,20 @@ static struct it87_data *it87_update_device(struct device *dev)
 		if (update_vbat) {
 			/* Cleared after each update, so reenable.  Value
 		 	  returned by this read will be previous value */	
-			it87_write_value(client, IT87_REG_CONFIG,
-			   it87_read_value(client, IT87_REG_CONFIG) | 0x40);
+			it87_write_value(data, IT87_REG_CONFIG,
+			   it87_read_value(data, IT87_REG_CONFIG) | 0x40);
 		}
 		for (i = 0; i <= 7; i++) {
 			data->in[i] =
-			    it87_read_value(client, IT87_REG_VIN(i));
+			    it87_read_value(data, IT87_REG_VIN(i));
 			data->in_min[i] =
-			    it87_read_value(client, IT87_REG_VIN_MIN(i));
+			    it87_read_value(data, IT87_REG_VIN_MIN(i));
 			data->in_max[i] =
-			    it87_read_value(client, IT87_REG_VIN_MAX(i));
+			    it87_read_value(data, IT87_REG_VIN_MAX(i));
 		}
 		/* in8 (battery) has no limit registers */
 		data->in[8] =
-		    it87_read_value(client, IT87_REG_VIN(8));
+		    it87_read_value(data, IT87_REG_VIN(8));
 
 		for (i = 0; i < 3; i++) {
 			/* Skip disabled fans */
@@ -1319,46 +1320,47 @@ static struct it87_data *it87_update_device(struct device *dev)
 				continue;
 
 			data->fan_min[i] =
-			    it87_read_value(client, IT87_REG_FAN_MIN(i));
-			data->fan[i] = it87_read_value(client,
+			    it87_read_value(data, IT87_REG_FAN_MIN(i));
+			data->fan[i] = it87_read_value(data,
 				       IT87_REG_FAN(i));
 			/* Add high byte if in 16-bit mode */
 			if (data->type == it8716 || data->type == it8718) {
-				data->fan[i] |= it87_read_value(client,
+				data->fan[i] |= it87_read_value(data,
 						IT87_REG_FANX(i)) << 8;
-				data->fan_min[i] |= it87_read_value(client,
+				data->fan_min[i] |= it87_read_value(data,
 						IT87_REG_FANX_MIN(i)) << 8;
 			}
 		}
 		for (i = 0; i < 3; i++) {
 			data->temp[i] =
-			    it87_read_value(client, IT87_REG_TEMP(i));
+			    it87_read_value(data, IT87_REG_TEMP(i));
 			data->temp_high[i] =
-			    it87_read_value(client, IT87_REG_TEMP_HIGH(i));
+			    it87_read_value(data, IT87_REG_TEMP_HIGH(i));
 			data->temp_low[i] =
-			    it87_read_value(client, IT87_REG_TEMP_LOW(i));
+			    it87_read_value(data, IT87_REG_TEMP_LOW(i));
 		}
 
 		/* Newer chips don't have clock dividers */
 		if ((data->has_fan & 0x07) && data->type != it8716
 		 && data->type != it8718) {
-			i = it87_read_value(client, IT87_REG_FAN_DIV);
+			i = it87_read_value(data, IT87_REG_FAN_DIV);
 			data->fan_div[0] = i & 0x07;
 			data->fan_div[1] = (i >> 3) & 0x07;
 			data->fan_div[2] = (i & 0x40) ? 3 : 1;
 		}
 
 		data->alarms =
-			it87_read_value(client, IT87_REG_ALARM1) |
-			(it87_read_value(client, IT87_REG_ALARM2) << 8) |
-			(it87_read_value(client, IT87_REG_ALARM3) << 16);
-		data->fan_main_ctrl = it87_read_value(client, IT87_REG_FAN_MAIN_CTRL);
-		data->fan_ctl = it87_read_value(client, IT87_REG_FAN_CTL);
-
-		data->sensor = it87_read_value(client, IT87_REG_TEMP_ENABLE);
+			it87_read_value(data, IT87_REG_ALARM1) |
+			(it87_read_value(data, IT87_REG_ALARM2) << 8) |
+			(it87_read_value(data, IT87_REG_ALARM3) << 16);
+		data->fan_main_ctrl = it87_read_value(data,
+				IT87_REG_FAN_MAIN_CTRL);
+		data->fan_ctl = it87_read_value(data, IT87_REG_FAN_CTL);
+
+		data->sensor = it87_read_value(data, IT87_REG_TEMP_ENABLE);
 		/* The 8705 does not have VID capability */
 		if (data->type == it8712 || data->type == it8716) {
-			data->vid = it87_read_value(client, IT87_REG_VID);
+			data->vid = it87_read_value(data, IT87_REG_VID);
 			/* The older IT8712F revisions had only 5 VID pins,
 			   but we assume it is always safe to read 6 bits. */
 			data->vid &= 0x3f;
@@ -1372,24 +1374,85 @@ static struct it87_data *it87_update_device(struct device *dev)
 	return data;
 }
 
+static int __init it87_device_add(unsigned short address,
+				  const struct it87_sio_data *sio_data)
+{
+	struct resource res = {
+		.start	= address ,
+		.end	= address + IT87_EXTENT - 1,
+		.name	= DRVNAME,
+		.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;
+	}
+
+	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_data(pdev, sio_data,
+				       sizeof(struct it87_sio_data));
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		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 sm_it87_init(void)
 {
-	int res;
+	int err;
+	unsigned short isa_address=0;
+	struct it87_sio_data sio_data;
+
+	err = it87_find(&isa_address, &sio_data);
+	if (err)
+		return err;
+	err = platform_driver_register(&it87_driver);
+	if (err)
+		return err;
 
-	if ((res = it87_find(&isa_address)))
-		return res;
-	return i2c_isa_add_driver(&it87_isa_driver);
+	err = it87_device_add(isa_address, &sio_data);
+	if (err){
+		platform_driver_unregister(&it87_driver);
+		return err;
+	}
+
+	return 0;
 }
 
 static void __exit sm_it87_exit(void)
 {
-	i2c_isa_del_driver(&it87_isa_driver);
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&it87_driver);
 }
 
 
 MODULE_AUTHOR("Chris Gauthron <chrisg@0-in.com>, "
 	      "Jean Delvare <khali@linux-fr.org>");
-MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F, SiS950 driver");
+MODULE_DESCRIPTION("IT8705F/8712F/8716F/8718F/8726F, SiS950 driver");
 module_param(update_vbat, bool, 0);
 MODULE_PARM_DESC(update_vbat, "Update vbat if set else return powerup value");
 module_param(fix_pwm_polarity, bool, 0);
diff --git a/drivers/hwmon/lm63.c b/drivers/hwmon/lm63.c
index d69f3cf07122..2162d69a8c06 100644
--- a/drivers/hwmon/lm63.c
+++ b/drivers/hwmon/lm63.c
@@ -364,7 +364,7 @@ static DEVICE_ATTR(temp2_crit_hyst, S_IWUSR | S_IRUGO, show_temp2_crit_hyst,
 /* Individual alarm files */
 static SENSOR_DEVICE_ATTR(fan1_min_alarm, S_IRUGO, show_alarm, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
 static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
 static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
@@ -383,7 +383,7 @@ static struct attribute *lm63_attributes[] = {
 	&dev_attr_temp2_crit_hyst.attr,
 
 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
diff --git a/drivers/hwmon/lm78.c b/drivers/hwmon/lm78.c
index 9fb572f03ba5..6eea3476b90c 100644
--- a/drivers/hwmon/lm78.c
+++ b/drivers/hwmon/lm78.c
@@ -864,7 +864,7 @@ static int __init lm78_isa_found(unsigned short address)
 	/* Determine the chip type */
 	outb_p(LM78_REG_CHIPID, address + LM78_ADDR_REG_OFFSET);
 	val = inb_p(address + LM78_DATA_REG_OFFSET);
-	if (val == 0x00			/* LM78 */
+	if (val == 0x00 || val == 0x20	/* LM78 */
 	 || val == 0x40			/* LM78-J */
 	 || (val & 0xfe) == 0xc0)	/* LM79 */
 		found = 1;
@@ -882,7 +882,7 @@ static int __init lm78_isa_device_add(unsigned short address)
 {
 	struct resource res = {
 		.start	= address,
-		.end	= address + LM78_EXTENT,
+		.end	= address + LM78_EXTENT - 1,
 		.name	= "lm78",
 		.flags	= IORESOURCE_IO,
 	};
diff --git a/drivers/hwmon/lm83.c b/drivers/hwmon/lm83.c
index feb87b41e986..654c0f73464d 100644
--- a/drivers/hwmon/lm83.c
+++ b/drivers/hwmon/lm83.c
@@ -223,14 +223,14 @@ static SENSOR_DEVICE_ATTR(temp4_crit, S_IRUGO, show_temp, NULL, 8);
 /* Individual alarm files */
 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp3_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 2);
 static SENSOR_DEVICE_ATTR(temp3_max_alarm, S_IRUGO, show_alarm, NULL, 4);
 static SENSOR_DEVICE_ATTR(temp1_max_alarm, S_IRUGO, show_alarm, NULL, 6);
 static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 8);
 static SENSOR_DEVICE_ATTR(temp4_crit_alarm, S_IRUGO, show_alarm, NULL, 9);
-static SENSOR_DEVICE_ATTR(temp4_input_fault, S_IRUGO, show_alarm, NULL, 10);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_alarm, NULL, 10);
 static SENSOR_DEVICE_ATTR(temp4_max_alarm, S_IRUGO, show_alarm, NULL, 12);
-static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 13);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 13);
 static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 15);
 /* Raw alarm file for compatibility */
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
@@ -245,7 +245,7 @@ static struct attribute *lm83_attributes[] = {
 
 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp3_crit_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp3_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
 	&sensor_dev_attr_temp3_max_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp1_max_alarm.dev_attr.attr,
 	&dev_attr_alarms.attr,
@@ -266,9 +266,9 @@ static struct attribute *lm83_attributes_opt[] = {
 
 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp4_crit_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp4_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
 	&sensor_dev_attr_temp4_max_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
 	NULL
 };
diff --git a/drivers/hwmon/lm90.c b/drivers/hwmon/lm90.c
index 6882ce75feee..af541d67245d 100644
--- a/drivers/hwmon/lm90.c
+++ b/drivers/hwmon/lm90.c
@@ -43,6 +43,13 @@
  * variants. The extra address and features of the MAX6659 are not
  * supported by this driver.
  *
+ * This driver also supports the MAX6680 and MAX6681, two other sensor
+ * chips made by Maxim. These are quite similar to the other Maxim
+ * chips. Complete datasheet can be obtained at:
+ *   http://www.maxim-ic.com/quick_view2.cfm/qv_pk/3370
+ * The MAX6680 and MAX6681 only differ in the pinout so they can be
+ * treated identically.
+ *
  * This driver also supports the ADT7461 chip from Analog Devices but
  * only in its "compatability mode". If an ADT7461 chip is found but
  * is configured in non-compatible mode (where its temperature
@@ -84,20 +91,25 @@
 /*
  * Addresses to scan
  * Address is fully defined internally and cannot be changed except for
- * MAX6659.
+ * MAX6659, MAX6680 and MAX6681.
  * LM86, LM89, LM90, LM99, ADM1032, ADM1032-1, ADT7461, MAX6657 and MAX6658
  * have address 0x4c.
  * ADM1032-2, ADT7461-2, LM89-1, and LM99-1 have address 0x4d.
  * MAX6659 can have address 0x4c, 0x4d or 0x4e (unsupported).
+ * MAX6680 and MAX6681 can have address 0x18, 0x19, 0x1a, 0x29, 0x2a, 0x2b,
+ * 0x4c, 0x4d or 0x4e.
  */
 
-static unsigned short normal_i2c[] = { 0x4c, 0x4d, I2C_CLIENT_END };
+static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
+				       0x29, 0x2a, 0x2b,
+				       0x4c, 0x4d, 0x4e,
+				       I2C_CLIENT_END };
 
 /*
  * Insmod parameters
  */
 
-I2C_CLIENT_INSMOD_6(lm90, adm1032, lm99, lm86, max6657, adt7461);
+I2C_CLIENT_INSMOD_7(lm90, adm1032, lm99, lm86, max6657, adt7461, max6680);
 
 /*
  * The LM90 registers
@@ -359,7 +371,7 @@ static SENSOR_DEVICE_ATTR(temp2_crit_hyst, S_IRUGO, show_temphyst, NULL, 4);
 /* Individual alarm files */
 static SENSOR_DEVICE_ATTR(temp1_crit_alarm, S_IRUGO, show_alarm, NULL, 0);
 static SENSOR_DEVICE_ATTR(temp2_crit_alarm, S_IRUGO, show_alarm, NULL, 1);
-static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 2);
 static SENSOR_DEVICE_ATTR(temp2_min_alarm, S_IRUGO, show_alarm, NULL, 3);
 static SENSOR_DEVICE_ATTR(temp2_max_alarm, S_IRUGO, show_alarm, NULL, 4);
 static SENSOR_DEVICE_ATTR(temp1_min_alarm, S_IRUGO, show_alarm, NULL, 5);
@@ -381,7 +393,7 @@ static struct attribute *lm90_attributes[] = {
 
 	&sensor_dev_attr_temp1_crit_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp2_crit_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
 	&sensor_dev_attr_temp2_min_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp2_max_alarm.dev_attr.attr,
 	&sensor_dev_attr_temp1_min_alarm.dev_attr.attr,
@@ -429,7 +441,7 @@ static DEVICE_ATTR(pec, S_IWUSR | S_IRUGO, show_pec, set_pec);
  */
 
 /* The ADM1032 supports PEC but not on write byte transactions, so we need
-   to explicitely ask for a transaction without PEC. */
+   to explicitly ask for a transaction without PEC. */
 static inline s32 adm1032_write_byte(struct i2c_client *client, u8 value)
 {
 	return i2c_smbus_xfer(client->adapter, client->addr,
@@ -525,7 +537,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
 		 		  &reg_convrate) < 0)
 			goto exit_free;
 		
-		if (man_id == 0x01) { /* National Semiconductor */
+		if ((address == 0x4C || address == 0x4D)
+		 && man_id == 0x01) { /* National Semiconductor */
 			u8 reg_config2;
 
 			if (lm90_read_reg(new_client, LM90_REG_R_CONFIG2,
@@ -548,7 +561,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
 				}
 			}
 		} else
-		if (man_id == 0x41) { /* Analog Devices */
+		if ((address == 0x4C || address == 0x4D)
+		 && man_id == 0x41) { /* Analog Devices */
 			if ((chip_id & 0xF0) == 0x40 /* ADM1032 */
 			 && (reg_config1 & 0x3F) == 0x00
 			 && reg_convrate <= 0x0A) {
@@ -562,18 +576,30 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
 		} else
 		if (man_id == 0x4D) { /* Maxim */
 			/*
-			 * The Maxim variants do NOT have a chip_id register.
-			 * Reading from that address will return the last read
-			 * value, which in our case is those of the man_id
-			 * register. Likewise, the config1 register seems to
-			 * lack a low nibble, so the value will be those of the
-			 * previous read, so in our case those of the man_id
-			 * register.
+			 * The MAX6657, MAX6658 and MAX6659 do NOT have a
+			 * chip_id register. Reading from that address will
+			 * return the last read value, which in our case is
+			 * those of the man_id register. Likewise, the config1
+			 * register seems to lack a low nibble, so the value
+			 * will be those of the previous read, so in our case
+			 * those of the man_id register.
 			 */
 			if (chip_id == man_id
+			 && (address == 0x4C || address == 0x4D)
 			 && (reg_config1 & 0x1F) == (man_id & 0x0F)
 			 && reg_convrate <= 0x09) {
 			 	kind = max6657;
+			} else
+			/* The chip_id register of the MAX6680 and MAX6681
+			 * holds the revision of the chip.
+			 * the lowest bit of the config1 register is unused
+			 * and should return zero when read, so should the
+			 * second to last bit of config1 (software reset)
+			 */
+			if (chip_id == 0x01
+			 && (reg_config1 & 0x03) == 0x00
+			 && reg_convrate <= 0x07) {
+			 	kind = max6680;
 			}
 		}
 
@@ -599,6 +625,8 @@ static int lm90_detect(struct i2c_adapter *adapter, int address, int kind)
 		name = "lm86";
 	} else if (kind == max6657) {
 		name = "max6657";
+	} else if (kind == max6680) {
+		name = "max6680";
 	} else if (kind == adt7461) {
 		name = "adt7461";
 	}
@@ -646,7 +674,8 @@ exit:
 
 static void lm90_init_client(struct i2c_client *client)
 {
-	u8 config;
+	u8 config, config_orig;
+	struct lm90_data *data = i2c_get_clientdata(client);
 
 	/*
 	 * Start the conversions.
@@ -657,9 +686,20 @@ static void lm90_init_client(struct i2c_client *client)
 		dev_warn(&client->dev, "Initialization failed!\n");
 		return;
 	}
-	if (config & 0x40)
-		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1,
-					  config & 0xBF); /* run */
+	config_orig = config;
+
+	/*
+	 * Put MAX6680/MAX8881 into extended resolution (bit 0x10,
+	 * 0.125 degree resolution) and range (0x08, extend range
+	 * to -64 degree) mode for the remote temperature sensor.
+	 */
+	if (data->kind == max6680) {
+		config |= 0x18;
+	}
+
+	config &= 0xBF;	/* run */
+	if (config != config_orig) /* Only write if changed */
+		i2c_smbus_write_byte_data(client, LM90_REG_W_CONFIG1, config);
 }
 
 static int lm90_detach_client(struct i2c_client *client)
diff --git a/drivers/hwmon/lm93.c b/drivers/hwmon/lm93.c
new file mode 100644
index 000000000000..d84f8bf6f284
--- /dev/null
+++ b/drivers/hwmon/lm93.c
@@ -0,0 +1,2655 @@
+/*
+    lm93.c - Part of lm_sensors, Linux kernel modules for hardware monitoring
+
+    Author/Maintainer: Mark M. Hoffman <mhoffman@lightlink.com>
+	Copyright (c) 2004 Utilitek Systems, Inc.
+
+    derived in part from lm78.c:
+	Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>
+
+    derived in part from lm85.c:
+	Copyright (c) 2002, 2003 Philip Pokorny <ppokorny@penguincomputing.com>
+	Copyright (c) 2003       Margit Schubert-While <margitsw@t-online.de>
+
+    derived in part from w83l785ts.c:
+	Copyright (c) 2003-2004 Jean Delvare <khali@linux-fr.org>
+
+    Ported to Linux 2.6 by Eric J. Bowersox <ericb@aspsys.com>
+	Copyright (c) 2005 Aspen Systems, Inc.
+
+    Adapted to 2.6.20 by Carsten Emde <cbe@osadl.org>
+        Copyright (c) 2006 Carsten Emde, Open Source Automation Development Lab
+
+    Modified for mainline integration by Hans J. Koch <hjk@linutronix.de>
+        Copyright (c) 2007 Hans J. Koch, Linutronix GmbH
+
+    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/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
+#include <linux/err.h>
+#include <linux/delay.h>
+
+/* LM93 REGISTER ADDRESSES */
+
+/* miscellaneous */
+#define LM93_REG_MFR_ID			0x3e
+#define LM93_REG_VER			0x3f
+#define LM93_REG_STATUS_CONTROL		0xe2
+#define LM93_REG_CONFIG			0xe3
+#define LM93_REG_SLEEP_CONTROL		0xe4
+
+/* alarm values start here */
+#define LM93_REG_HOST_ERROR_1		0x48
+
+/* voltage inputs: in1-in16 (nr => 0-15) */
+#define LM93_REG_IN(nr)			(0x56 + (nr))
+#define LM93_REG_IN_MIN(nr)		(0x90 + (nr) * 2)
+#define LM93_REG_IN_MAX(nr)		(0x91 + (nr) * 2)
+
+/* temperature inputs: temp1-temp4 (nr => 0-3) */
+#define LM93_REG_TEMP(nr)		(0x50 + (nr))
+#define LM93_REG_TEMP_MIN(nr)		(0x78 + (nr) * 2)
+#define LM93_REG_TEMP_MAX(nr)		(0x79 + (nr) * 2)
+
+/* temp[1-4]_auto_boost (nr => 0-3) */
+#define LM93_REG_BOOST(nr)		(0x80 + (nr))
+
+/* #PROCHOT inputs: prochot1-prochot2 (nr => 0-1) */
+#define LM93_REG_PROCHOT_CUR(nr)	(0x67 + (nr) * 2)
+#define LM93_REG_PROCHOT_AVG(nr)	(0x68 + (nr) * 2)
+#define LM93_REG_PROCHOT_MAX(nr)	(0xb0 + (nr))
+
+/* fan tach inputs: fan1-fan4 (nr => 0-3) */
+#define LM93_REG_FAN(nr)		(0x6e + (nr) * 2)
+#define LM93_REG_FAN_MIN(nr)		(0xb4 + (nr) * 2)
+
+/* pwm outputs: pwm1-pwm2 (nr => 0-1, reg => 0-3) */
+#define LM93_REG_PWM_CTL(nr,reg)	(0xc8 + (reg) + (nr) * 4)
+#define LM93_PWM_CTL1	0x0
+#define LM93_PWM_CTL2	0x1
+#define LM93_PWM_CTL3	0x2
+#define LM93_PWM_CTL4	0x3
+
+/* GPIO input state */
+#define LM93_REG_GPI			0x6b
+
+/* vid inputs: vid1-vid2 (nr => 0-1) */
+#define LM93_REG_VID(nr)		(0x6c + (nr))
+
+/* vccp1 & vccp2: VID relative inputs (nr => 0-1) */
+#define LM93_REG_VCCP_LIMIT_OFF(nr)	(0xb2 + (nr))
+
+/* temp[1-4]_auto_boost_hyst */
+#define LM93_REG_BOOST_HYST_12		0xc0
+#define LM93_REG_BOOST_HYST_34		0xc1
+#define LM93_REG_BOOST_HYST(nr)		(0xc0 + (nr)/2)
+
+/* temp[1-4]_auto_pwm_[min|hyst] */
+#define LM93_REG_PWM_MIN_HYST_12	0xc3
+#define LM93_REG_PWM_MIN_HYST_34	0xc4
+#define LM93_REG_PWM_MIN_HYST(nr)	(0xc3 + (nr)/2)
+
+/* prochot_override & prochot_interval */
+#define LM93_REG_PROCHOT_OVERRIDE	0xc6
+#define LM93_REG_PROCHOT_INTERVAL	0xc7
+
+/* temp[1-4]_auto_base (nr => 0-3) */
+#define LM93_REG_TEMP_BASE(nr)		(0xd0 + (nr))
+
+/* temp[1-4]_auto_offsets (step => 0-11) */
+#define LM93_REG_TEMP_OFFSET(step)	(0xd4 + (step))
+
+/* #PROCHOT & #VRDHOT PWM ramp control */
+#define LM93_REG_PWM_RAMP_CTL		0xbf
+
+/* miscellaneous */
+#define LM93_REG_SFC1		0xbc
+#define LM93_REG_SFC2		0xbd
+#define LM93_REG_GPI_VID_CTL	0xbe
+#define LM93_REG_SF_TACH_TO_PWM	0xe0
+
+/* error masks */
+#define LM93_REG_GPI_ERR_MASK	0xec
+#define LM93_REG_MISC_ERR_MASK	0xed
+
+/* LM93 REGISTER VALUES */
+#define LM93_MFR_ID		0x73
+#define LM93_MFR_ID_PROTOTYPE	0x72
+
+/* SMBus capabilities */
+#define LM93_SMBUS_FUNC_FULL (I2C_FUNC_SMBUS_BYTE_DATA | \
+		I2C_FUNC_SMBUS_WORD_DATA | I2C_FUNC_SMBUS_BLOCK_DATA)
+#define LM93_SMBUS_FUNC_MIN  (I2C_FUNC_SMBUS_BYTE_DATA | \
+		I2C_FUNC_SMBUS_WORD_DATA)
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_1(lm93);
+
+static int disable_block;
+module_param(disable_block, bool, 0);
+MODULE_PARM_DESC(disable_block,
+	"Set to non-zero to disable SMBus block data transactions.");
+
+static int init;
+module_param(init, bool, 0);
+MODULE_PARM_DESC(init, "Set to non-zero to force chip initialization.");
+
+static int vccp_limit_type[2] = {0,0};
+module_param_array(vccp_limit_type, int, NULL, 0);
+MODULE_PARM_DESC(vccp_limit_type, "Configures in7 and in8 limit modes.");
+
+static int vid_agtl;
+module_param(vid_agtl, int, 0);
+MODULE_PARM_DESC(vid_agtl, "Configures VID pin input thresholds.");
+
+/* Driver data */
+static struct i2c_driver lm93_driver;
+
+/* LM93 BLOCK READ COMMANDS */
+static const struct { u8 cmd; u8 len; } lm93_block_read_cmds[12] = {
+	{ 0xf2,  8 },
+	{ 0xf3,  8 },
+	{ 0xf4,  6 },
+	{ 0xf5, 16 },
+	{ 0xf6,  4 },
+	{ 0xf7,  8 },
+	{ 0xf8, 12 },
+	{ 0xf9, 32 },
+	{ 0xfa,  8 },
+	{ 0xfb,  8 },
+	{ 0xfc, 16 },
+	{ 0xfd,  9 },
+};
+
+/* ALARMS: SYSCTL format described further below
+   REG: 64 bits in 8 registers, as immediately below */
+struct block1_t {
+	u8 host_status_1;
+	u8 host_status_2;
+	u8 host_status_3;
+	u8 host_status_4;
+	u8 p1_prochot_status;
+	u8 p2_prochot_status;
+	u8 gpi_status;
+	u8 fan_status;
+};
+
+/*
+ * Client-specific data
+ */
+struct lm93_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+
+	struct mutex update_lock;
+	unsigned long last_updated;	/* In jiffies */
+
+	/* client update function */
+	void (*update)(struct lm93_data *, struct i2c_client *);
+
+	char valid; /* !=0 if following fields are valid */
+
+	/* register values, arranged by block read groups */
+	struct block1_t block1;
+
+	/* temp1 - temp4: unfiltered readings
+	   temp1 - temp2: filtered readings */
+	u8 block2[6];
+
+	/* vin1 - vin16: readings */
+	u8 block3[16];
+
+	/* prochot1 - prochot2: readings */
+	struct {
+		u8 cur;
+		u8 avg;
+	} block4[2];
+
+	/* fan counts 1-4 => 14-bits, LE, *left* justified */
+	u16 block5[4];
+
+	/* block6 has a lot of data we don't need */
+	struct {
+		u8 min;
+		u8 max;
+	} temp_lim[4];
+
+	/* vin1 - vin16: low and high limits */
+	struct {
+		u8 min;
+		u8 max;
+	} block7[16];
+
+	/* fan count limits 1-4 => same format as block5 */
+	u16 block8[4];
+
+	/* pwm control registers (2 pwms, 4 regs) */
+	u8 block9[2][4];
+
+	/* auto/pwm base temp and offset temp registers */
+	struct {
+		u8 base[4];
+		u8 offset[12];
+	} block10;
+
+	/* master config register */
+	u8 config;
+
+	/* VID1 & VID2 => register format, 6-bits, right justified */
+	u8 vid[2];
+
+	/* prochot1 - prochot2: limits */
+	u8 prochot_max[2];
+
+	/* vccp1 & vccp2 (in7 & in8): VID relative limits (register format) */
+	u8 vccp_limits[2];
+
+	/* GPIO input state (register format, i.e. inverted) */
+	u8 gpi;
+
+	/* #PROCHOT override (register format) */
+	u8 prochot_override;
+
+	/* #PROCHOT intervals (register format) */
+	u8 prochot_interval;
+
+	/* Fan Boost Temperatures (register format) */
+	u8 boost[4];
+
+	/* Fan Boost Hysteresis (register format) */
+	u8 boost_hyst[2];
+
+	/* Temperature Zone Min. PWM & Hysteresis (register format) */
+	u8 auto_pwm_min_hyst[2];
+
+	/* #PROCHOT & #VRDHOT PWM Ramp Control */
+	u8 pwm_ramp_ctl;
+
+	/* miscellaneous setup regs */
+	u8 sfc1;
+	u8 sfc2;
+	u8 sf_tach_to_pwm;
+
+	/* The two PWM CTL2  registers can read something other than what was
+	   last written for the OVR_DC field (duty cycle override).  So, we
+	   save the user-commanded value here. */
+	u8 pwm_override[2];
+};
+
+/* VID:	mV
+   REG: 6-bits, right justified, *always* using Intel VRM/VRD 10 */
+static int LM93_VID_FROM_REG(u8 reg)
+{
+	return vid_from_reg((reg & 0x3f), 100);
+}
+
+/* min, max, and nominal register values, per channel (u8) */
+static const u8 lm93_vin_reg_min[16] = {
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+	0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xae,
+};
+static const u8 lm93_vin_reg_max[16] = {
+	0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+	0xff, 0xfa, 0xff, 0xff, 0xff, 0xff, 0xff, 0xd1,
+};
+/* Values from the datasheet. They're here for documentation only.
+static const u8 lm93_vin_reg_nom[16] = {
+	0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0,
+	0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0xc0, 0x40, 0xc0,
+};
+*/
+
+/* min, max, and nominal voltage readings, per channel (mV)*/
+static const unsigned long lm93_vin_val_min[16] = {
+	0, 0, 0, 0, 0, 0, 0, 0,
+	0, 0, 0, 0, 0, 0, 0, 3000,
+};
+
+static const unsigned long lm93_vin_val_max[16] = {
+	1236, 1236, 1236, 1600, 2000, 2000, 1600, 1600,
+	4400, 6500, 3333, 2625, 1312, 1312, 1236, 3600,
+};
+/* Values from the datasheet. They're here for documentation only.
+static const unsigned long lm93_vin_val_nom[16] = {
+	 927,  927,  927, 1200, 1500, 1500, 1200, 1200,
+	3300, 5000, 2500, 1969,  984,  984,  309, 3300,
+};
+*/
+
+static unsigned LM93_IN_FROM_REG(int nr, u8 reg)
+{
+	const long uV_max = lm93_vin_val_max[nr] * 1000;
+	const long uV_min = lm93_vin_val_min[nr] * 1000;
+
+	const long slope = (uV_max - uV_min) /
+		(lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]);
+	const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
+
+	return (slope * reg + intercept + 500) / 1000;
+}
+
+/* IN: mV, limits determined by channel nr
+   REG: scaling determined by channel nr */
+static u8 LM93_IN_TO_REG(int nr, unsigned val)
+{
+	/* range limit */
+	const long mV = SENSORS_LIMIT(val,
+		lm93_vin_val_min[nr], lm93_vin_val_max[nr]);
+
+	/* try not to lose too much precision here */
+	const long uV = mV * 1000;
+	const long uV_max = lm93_vin_val_max[nr] * 1000;
+	const long uV_min = lm93_vin_val_min[nr] * 1000;
+
+	/* convert */
+	const long slope = (uV_max - uV_min) /
+		(lm93_vin_reg_max[nr] - lm93_vin_reg_min[nr]);
+	const long intercept = uV_min - slope * lm93_vin_reg_min[nr];
+
+	u8 result = ((uV - intercept + (slope/2)) / slope);
+	result = SENSORS_LIMIT(result,
+			lm93_vin_reg_min[nr], lm93_vin_reg_max[nr]);
+	return result;
+}
+
+/* vid in mV, upper == 0 indicates low limit, otherwise upper limit */
+static unsigned LM93_IN_REL_FROM_REG(u8 reg, int upper, int vid)
+{
+	const long uV_offset = upper ? (((reg >> 4 & 0x0f) + 1) * 12500) :
+				(((reg >> 0 & 0x0f) + 1) * -25000);
+	const long uV_vid = vid * 1000;
+	return (uV_vid + uV_offset + 5000) / 10000;
+}
+
+#define LM93_IN_MIN_FROM_REG(reg,vid)	LM93_IN_REL_FROM_REG(reg,0,vid)
+#define LM93_IN_MAX_FROM_REG(reg,vid)	LM93_IN_REL_FROM_REG(reg,1,vid)
+
+/* vid in mV , upper == 0 indicates low limit, otherwise upper limit
+   upper also determines which nibble of the register is returned
+   (the other nibble will be 0x0) */
+static u8 LM93_IN_REL_TO_REG(unsigned val, int upper, int vid)
+{
+	long uV_offset = vid * 1000 - val * 10000;
+	if (upper) {
+		uV_offset = SENSORS_LIMIT(uV_offset, 12500, 200000);
+		return (u8)((uV_offset /  12500 - 1) << 4);
+	} else {
+		uV_offset = SENSORS_LIMIT(uV_offset, -400000, -25000);
+		return (u8)((uV_offset / -25000 - 1) << 0);
+	}
+}
+
+/* TEMP: 1/1000 degrees C (-128C to +127C)
+   REG: 1C/bit, two's complement */
+static int LM93_TEMP_FROM_REG(u8 reg)
+{
+	return (s8)reg * 1000;
+}
+
+#define LM93_TEMP_MIN (-128000)
+#define LM93_TEMP_MAX ( 127000)
+
+/* TEMP: 1/1000 degrees C (-128C to +127C)
+   REG: 1C/bit, two's complement */
+static u8 LM93_TEMP_TO_REG(int temp)
+{
+	int ntemp = SENSORS_LIMIT(temp, LM93_TEMP_MIN, LM93_TEMP_MAX);
+	ntemp += (ntemp<0 ? -500 : 500);
+	return (u8)(ntemp / 1000);
+}
+
+/* Determine 4-bit temperature offset resolution */
+static int LM93_TEMP_OFFSET_MODE_FROM_REG(u8 sfc2, int nr)
+{
+	/* mode: 0 => 1C/bit, nonzero => 0.5C/bit */
+	return sfc2 & (nr < 2 ? 0x10 : 0x20);
+}
+
+/* This function is common to all 4-bit temperature offsets
+   reg is 4 bits right justified
+   mode 0 => 1C/bit, mode !0 => 0.5C/bit */
+static int LM93_TEMP_OFFSET_FROM_REG(u8 reg, int mode)
+{
+	return (reg & 0x0f) * (mode ? 5 : 10);
+}
+
+#define LM93_TEMP_OFFSET_MIN  (  0)
+#define LM93_TEMP_OFFSET_MAX0 (150)
+#define LM93_TEMP_OFFSET_MAX1 ( 75)
+
+/* This function is common to all 4-bit temperature offsets
+   returns 4 bits right justified
+   mode 0 => 1C/bit, mode !0 => 0.5C/bit */
+static u8 LM93_TEMP_OFFSET_TO_REG(int off, int mode)
+{
+	int factor = mode ? 5 : 10;
+
+	off = SENSORS_LIMIT(off, LM93_TEMP_OFFSET_MIN,
+		mode ? LM93_TEMP_OFFSET_MAX1 : LM93_TEMP_OFFSET_MAX0);
+	return (u8)((off + factor/2) / factor);
+}
+
+/* 0 <= nr <= 3 */
+static int LM93_TEMP_AUTO_OFFSET_FROM_REG(u8 reg, int nr, int mode)
+{
+	/* temp1-temp2 (nr=0,1) use lower nibble */
+	if (nr < 2)
+		return LM93_TEMP_OFFSET_FROM_REG(reg & 0x0f, mode);
+
+	/* temp3-temp4 (nr=2,3) use upper nibble */
+	else
+		return LM93_TEMP_OFFSET_FROM_REG(reg >> 4 & 0x0f, mode);
+}
+
+/* TEMP: 1/10 degrees C (0C to +15C (mode 0) or +7.5C (mode non-zero))
+   REG: 1.0C/bit (mode 0) or 0.5C/bit (mode non-zero)
+   0 <= nr <= 3 */
+static u8 LM93_TEMP_AUTO_OFFSET_TO_REG(u8 old, int off, int nr, int mode)
+{
+	u8 new = LM93_TEMP_OFFSET_TO_REG(off, mode);
+
+	/* temp1-temp2 (nr=0,1) use lower nibble */
+	if (nr < 2)
+		return (old & 0xf0) | (new & 0x0f);
+
+	/* temp3-temp4 (nr=2,3) use upper nibble */
+	else
+		return (new << 4 & 0xf0) | (old & 0x0f);
+}
+
+static int LM93_AUTO_BOOST_HYST_FROM_REGS(struct lm93_data *data, int nr,
+		int mode)
+{
+	u8 reg;
+
+	switch (nr) {
+	case 0:
+		reg = data->boost_hyst[0] & 0x0f;
+		break;
+	case 1:
+		reg = data->boost_hyst[0] >> 4 & 0x0f;
+		break;
+	case 2:
+		reg = data->boost_hyst[1] & 0x0f;
+		break;
+	case 3:
+	default:
+		reg = data->boost_hyst[1] >> 4 & 0x0f;
+		break;
+	}
+
+	return LM93_TEMP_FROM_REG(data->boost[nr]) -
+			LM93_TEMP_OFFSET_FROM_REG(reg, mode);
+}
+
+static u8 LM93_AUTO_BOOST_HYST_TO_REG(struct lm93_data *data, long hyst,
+		int nr, int mode)
+{
+	u8 reg = LM93_TEMP_OFFSET_TO_REG(
+			(LM93_TEMP_FROM_REG(data->boost[nr]) - hyst), mode);
+
+	switch (nr) {
+	case 0:
+		reg = (data->boost_hyst[0] & 0xf0) | (reg & 0x0f);
+		break;
+	case 1:
+		reg = (reg << 4 & 0xf0) | (data->boost_hyst[0] & 0x0f);
+		break;
+	case 2:
+		reg = (data->boost_hyst[1] & 0xf0) | (reg & 0x0f);
+		break;
+	case 3:
+	default:
+		reg = (reg << 4 & 0xf0) | (data->boost_hyst[1] & 0x0f);
+		break;
+	}
+
+	return reg;
+}
+
+/* PWM: 0-255 per sensors documentation
+   REG: 0-13 as mapped below... right justified */
+typedef enum { LM93_PWM_MAP_HI_FREQ, LM93_PWM_MAP_LO_FREQ } pwm_freq_t;
+static int lm93_pwm_map[2][16] = {
+	{
+		0x00, /*   0.00% */ 0x40, /*  25.00% */
+		0x50, /*  31.25% */ 0x60, /*  37.50% */
+		0x70, /*  43.75% */ 0x80, /*  50.00% */
+		0x90, /*  56.25% */ 0xa0, /*  62.50% */
+		0xb0, /*  68.75% */ 0xc0, /*  75.00% */
+		0xd0, /*  81.25% */ 0xe0, /*  87.50% */
+		0xf0, /*  93.75% */ 0xff, /* 100.00% */
+		0xff, 0xff, /* 14, 15 are reserved and should never occur */
+	},
+	{
+		0x00, /*   0.00% */ 0x40, /*  25.00% */
+		0x49, /*  28.57% */ 0x52, /*  32.14% */
+		0x5b, /*  35.71% */ 0x64, /*  39.29% */
+		0x6d, /*  42.86% */ 0x76, /*  46.43% */
+		0x80, /*  50.00% */ 0x89, /*  53.57% */
+		0x92, /*  57.14% */ 0xb6, /*  71.43% */
+		0xdb, /*  85.71% */ 0xff, /* 100.00% */
+		0xff, 0xff, /* 14, 15 are reserved and should never occur */
+	},
+};
+
+static int LM93_PWM_FROM_REG(u8 reg, pwm_freq_t freq)
+{
+	return lm93_pwm_map[freq][reg & 0x0f];
+}
+
+/* round up to nearest match */
+static u8 LM93_PWM_TO_REG(int pwm, pwm_freq_t freq)
+{
+	int i;
+	for (i = 0; i < 13; i++)
+		if (pwm <= lm93_pwm_map[freq][i])
+			break;
+
+	/* can fall through with i==13 */
+	return (u8)i;
+}
+
+static int LM93_FAN_FROM_REG(u16 regs)
+{
+	const u16 count = le16_to_cpu(regs) >> 2;
+	return count==0 ? -1 : count==0x3fff ? 0: 1350000 / count;
+}
+
+/*
+ * RPM: (82.5 to 1350000)
+ * REG: 14-bits, LE, *left* justified
+ */
+static u16 LM93_FAN_TO_REG(long rpm)
+{
+	u16 count, regs;
+
+	if (rpm == 0) {
+		count = 0x3fff;
+	} else {
+		rpm = SENSORS_LIMIT(rpm, 1, 1000000);
+		count = SENSORS_LIMIT((1350000 + rpm) / rpm, 1, 0x3ffe);
+	}
+
+	regs = count << 2;
+	return cpu_to_le16(regs);
+}
+
+/* PWM FREQ: HZ
+   REG: 0-7 as mapped below */
+static int lm93_pwm_freq_map[8] = {
+	22500, 96, 84, 72, 60, 48, 36, 12
+};
+
+static int LM93_PWM_FREQ_FROM_REG(u8 reg)
+{
+	return lm93_pwm_freq_map[reg & 0x07];
+}
+
+/* round up to nearest match */
+static u8 LM93_PWM_FREQ_TO_REG(int freq)
+{
+	int i;
+	for (i = 7; i > 0; i--)
+		if (freq <= lm93_pwm_freq_map[i])
+			break;
+
+	/* can fall through with i==0 */
+	return (u8)i;
+}
+
+/* TIME: 1/100 seconds
+ * REG: 0-7 as mapped below */
+static int lm93_spinup_time_map[8] = {
+	0, 10, 25, 40, 70, 100, 200, 400,
+};
+
+static int LM93_SPINUP_TIME_FROM_REG(u8 reg)
+{
+	return lm93_spinup_time_map[reg >> 5 & 0x07];
+}
+
+/* round up to nearest match */
+static u8 LM93_SPINUP_TIME_TO_REG(int time)
+{
+	int i;
+	for (i = 0; i < 7; i++)
+		if (time <= lm93_spinup_time_map[i])
+			break;
+
+	/* can fall through with i==8 */
+	return (u8)i;
+}
+
+#define LM93_RAMP_MIN 0
+#define LM93_RAMP_MAX 75
+
+static int LM93_RAMP_FROM_REG(u8 reg)
+{
+	return (reg & 0x0f) * 5;
+}
+
+/* RAMP: 1/100 seconds
+   REG: 50mS/bit 4-bits right justified */
+static u8 LM93_RAMP_TO_REG(int ramp)
+{
+	ramp = SENSORS_LIMIT(ramp, LM93_RAMP_MIN, LM93_RAMP_MAX);
+	return (u8)((ramp + 2) / 5);
+}
+
+/* PROCHOT: 0-255, 0 => 0%, 255 => > 96.6%
+ * REG: (same) */
+static u8 LM93_PROCHOT_TO_REG(long prochot)
+{
+	prochot = SENSORS_LIMIT(prochot, 0, 255);
+	return (u8)prochot;
+}
+
+/* PROCHOT-INTERVAL: 73 - 37200 (1/100 seconds)
+ * REG: 0-9 as mapped below */
+static int lm93_interval_map[10] = {
+	73, 146, 290, 580, 1170, 2330, 4660, 9320, 18600, 37200,
+};
+
+static int LM93_INTERVAL_FROM_REG(u8 reg)
+{
+	return lm93_interval_map[reg & 0x0f];
+}
+
+/* round up to nearest match */
+static u8 LM93_INTERVAL_TO_REG(long interval)
+{
+	int i;
+	for (i = 0; i < 9; i++)
+		if (interval <= lm93_interval_map[i])
+			break;
+
+	/* can fall through with i==9 */
+	return (u8)i;
+}
+
+/* GPIO: 0-255, GPIO0 is LSB
+ * REG: inverted */
+static unsigned LM93_GPI_FROM_REG(u8 reg)
+{
+	return ~reg & 0xff;
+}
+
+/* alarm bitmask definitions
+   The LM93 has nearly 64 bits of error status... I've pared that down to
+   what I think is a useful subset in order to fit it into 32 bits.
+
+   Especially note that the #VRD_HOT alarms are missing because we provide
+   that information as values in another sysfs file.
+
+   If libsensors is extended to support 64 bit values, this could be revisited.
+*/
+#define LM93_ALARM_IN1		0x00000001
+#define LM93_ALARM_IN2		0x00000002
+#define LM93_ALARM_IN3		0x00000004
+#define LM93_ALARM_IN4		0x00000008
+#define LM93_ALARM_IN5		0x00000010
+#define LM93_ALARM_IN6		0x00000020
+#define LM93_ALARM_IN7		0x00000040
+#define LM93_ALARM_IN8		0x00000080
+#define LM93_ALARM_IN9		0x00000100
+#define LM93_ALARM_IN10		0x00000200
+#define LM93_ALARM_IN11		0x00000400
+#define LM93_ALARM_IN12		0x00000800
+#define LM93_ALARM_IN13		0x00001000
+#define LM93_ALARM_IN14		0x00002000
+#define LM93_ALARM_IN15		0x00004000
+#define LM93_ALARM_IN16		0x00008000
+#define LM93_ALARM_FAN1		0x00010000
+#define LM93_ALARM_FAN2		0x00020000
+#define LM93_ALARM_FAN3		0x00040000
+#define LM93_ALARM_FAN4		0x00080000
+#define LM93_ALARM_PH1_ERR	0x00100000
+#define LM93_ALARM_PH2_ERR	0x00200000
+#define LM93_ALARM_SCSI1_ERR	0x00400000
+#define LM93_ALARM_SCSI2_ERR	0x00800000
+#define LM93_ALARM_DVDDP1_ERR	0x01000000
+#define LM93_ALARM_DVDDP2_ERR	0x02000000
+#define LM93_ALARM_D1_ERR	0x04000000
+#define LM93_ALARM_D2_ERR	0x08000000
+#define LM93_ALARM_TEMP1	0x10000000
+#define LM93_ALARM_TEMP2	0x20000000
+#define LM93_ALARM_TEMP3	0x40000000
+
+static unsigned LM93_ALARMS_FROM_REG(struct block1_t b1)
+{
+	unsigned result;
+	result  = b1.host_status_2 & 0x3f;
+
+	if (vccp_limit_type[0])
+		result |= (b1.host_status_4 & 0x10) << 2;
+	else
+		result |= b1.host_status_2 & 0x40;
+
+	if (vccp_limit_type[1])
+		result |= (b1.host_status_4 & 0x20) << 2;
+	else
+		result |= b1.host_status_2 & 0x80;
+
+	result |= b1.host_status_3 << 8;
+	result |= (b1.fan_status & 0x0f) << 16;
+	result |= (b1.p1_prochot_status & 0x80) << 13;
+	result |= (b1.p2_prochot_status & 0x80) << 14;
+	result |= (b1.host_status_4 & 0xfc) << 20;
+	result |= (b1.host_status_1 & 0x07) << 28;
+	return result;
+}
+
+#define MAX_RETRIES 5
+
+static u8 lm93_read_byte(struct i2c_client *client, u8 reg)
+{
+	int value, i;
+
+	/* retry in case of read errors */
+	for (i=1; i<=MAX_RETRIES; i++) {
+		if ((value = i2c_smbus_read_byte_data(client, reg)) >= 0) {
+			return value;
+		} else {
+			dev_warn(&client->dev,"lm93: read byte data failed, "
+				"address 0x%02x.\n", reg);
+			mdelay(i + 3);
+		}
+
+	}
+
+	/* <TODO> what to return in case of error? */
+	dev_err(&client->dev,"lm93: All read byte retries failed!!\n");
+	return 0;
+}
+
+static int lm93_write_byte(struct i2c_client *client, u8 reg, u8 value)
+{
+	int result;
+
+	/* <TODO> how to handle write errors? */
+	result = i2c_smbus_write_byte_data(client, reg, value);
+
+	if (result < 0)
+		dev_warn(&client->dev,"lm93: write byte data failed, "
+			 "0x%02x at address 0x%02x.\n", value, reg);
+
+	return result;
+}
+
+static u16 lm93_read_word(struct i2c_client *client, u8 reg)
+{
+	int value, i;
+
+	/* retry in case of read errors */
+	for (i=1; i<=MAX_RETRIES; i++) {
+		if ((value = i2c_smbus_read_word_data(client, reg)) >= 0) {
+			return value;
+		} else {
+			dev_warn(&client->dev,"lm93: read word data failed, "
+				 "address 0x%02x.\n", reg);
+			mdelay(i + 3);
+		}
+
+	}
+
+	/* <TODO> what to return in case of error? */
+	dev_err(&client->dev,"lm93: All read word retries failed!!\n");
+	return 0;
+}
+
+static int lm93_write_word(struct i2c_client *client, u8 reg, u16 value)
+{
+	int result;
+
+	/* <TODO> how to handle write errors? */
+	result = i2c_smbus_write_word_data(client, reg, value);
+
+	if (result < 0)
+		dev_warn(&client->dev,"lm93: write word data failed, "
+			 "0x%04x at address 0x%02x.\n", value, reg);
+
+	return result;
+}
+
+static u8 lm93_block_buffer[I2C_SMBUS_BLOCK_MAX];
+
+/*
+	read block data into values, retry if not expected length
+	fbn => index to lm93_block_read_cmds table
+		(Fixed Block Number - section 14.5.2 of LM93 datasheet)
+*/
+static void lm93_read_block(struct i2c_client *client, u8 fbn, u8 *values)
+{
+	int i, result=0;
+
+	for (i = 1; i <= MAX_RETRIES; i++) {
+		result = i2c_smbus_read_block_data(client,
+			lm93_block_read_cmds[fbn].cmd, lm93_block_buffer);
+
+		if (result == lm93_block_read_cmds[fbn].len) {
+			break;
+		} else {
+			dev_warn(&client->dev,"lm93: block read data failed, "
+				 "command 0x%02x.\n",
+				 lm93_block_read_cmds[fbn].cmd);
+			mdelay(i + 3);
+		}
+	}
+
+	if (result == lm93_block_read_cmds[fbn].len) {
+		memcpy(values,lm93_block_buffer,lm93_block_read_cmds[fbn].len);
+	} else {
+		/* <TODO> what to do in case of error? */
+	}
+}
+
+static struct lm93_data *lm93_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	const unsigned long interval = HZ + (HZ / 2);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + interval) ||
+		!data->valid) {
+
+		data->update(data, client);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+	return data;
+}
+
+/* update routine for data that has no corresponding SMBus block command */
+static void lm93_update_client_common(struct lm93_data *data,
+				      struct i2c_client *client)
+{
+	int i;
+	u8 *ptr;
+
+	/* temp1 - temp4: limits */
+	for (i = 0; i < 4; i++) {
+		data->temp_lim[i].min =
+			lm93_read_byte(client, LM93_REG_TEMP_MIN(i));
+		data->temp_lim[i].max =
+			lm93_read_byte(client, LM93_REG_TEMP_MAX(i));
+	}
+
+	/* config register */
+	data->config = lm93_read_byte(client, LM93_REG_CONFIG);
+
+	/* vid1 - vid2: values */
+	for (i = 0; i < 2; i++)
+		data->vid[i] = lm93_read_byte(client, LM93_REG_VID(i));
+
+	/* prochot1 - prochot2: limits */
+	for (i = 0; i < 2; i++)
+		data->prochot_max[i] = lm93_read_byte(client,
+				LM93_REG_PROCHOT_MAX(i));
+
+	/* vccp1 - vccp2: VID relative limits */
+	for (i = 0; i < 2; i++)
+		data->vccp_limits[i] = lm93_read_byte(client,
+				LM93_REG_VCCP_LIMIT_OFF(i));
+
+	/* GPIO input state */
+	data->gpi = lm93_read_byte(client, LM93_REG_GPI);
+
+	/* #PROCHOT override state */
+	data->prochot_override = lm93_read_byte(client,
+			LM93_REG_PROCHOT_OVERRIDE);
+
+	/* #PROCHOT intervals */
+	data->prochot_interval = lm93_read_byte(client,
+			LM93_REG_PROCHOT_INTERVAL);
+
+	/* Fan Boost Termperature registers */
+	for (i = 0; i < 4; i++)
+		data->boost[i] = lm93_read_byte(client, LM93_REG_BOOST(i));
+
+	/* Fan Boost Temperature Hyst. registers */
+	data->boost_hyst[0] = lm93_read_byte(client, LM93_REG_BOOST_HYST_12);
+	data->boost_hyst[1] = lm93_read_byte(client, LM93_REG_BOOST_HYST_34);
+
+	/* Temperature Zone Min. PWM & Hysteresis registers */
+	data->auto_pwm_min_hyst[0] =
+			lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_12);
+	data->auto_pwm_min_hyst[1] =
+			lm93_read_byte(client, LM93_REG_PWM_MIN_HYST_34);
+
+	/* #PROCHOT & #VRDHOT PWM Ramp Control register */
+	data->pwm_ramp_ctl = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL);
+
+	/* misc setup registers */
+	data->sfc1 = lm93_read_byte(client, LM93_REG_SFC1);
+	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);
+	data->sf_tach_to_pwm = lm93_read_byte(client,
+			LM93_REG_SF_TACH_TO_PWM);
+
+	/* write back alarm values to clear */
+	for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++)
+		lm93_write_byte(client, LM93_REG_HOST_ERROR_1 + i, *(ptr + i));
+}
+
+/* update routine which uses SMBus block data commands */
+static void lm93_update_client_full(struct lm93_data *data,
+				    struct i2c_client *client)
+{
+	dev_dbg(&client->dev,"starting device update (block data enabled)\n");
+
+	/* in1 - in16: values & limits */
+	lm93_read_block(client, 3, (u8 *)(data->block3));
+	lm93_read_block(client, 7, (u8 *)(data->block7));
+
+	/* temp1 - temp4: values */
+	lm93_read_block(client, 2, (u8 *)(data->block2));
+
+	/* prochot1 - prochot2: values */
+	lm93_read_block(client, 4, (u8 *)(data->block4));
+
+	/* fan1 - fan4: values & limits */
+	lm93_read_block(client, 5, (u8 *)(data->block5));
+	lm93_read_block(client, 8, (u8 *)(data->block8));
+
+	/* pmw control registers */
+	lm93_read_block(client, 9, (u8 *)(data->block9));
+
+	/* alarm values */
+	lm93_read_block(client, 1, (u8 *)(&data->block1));
+
+	/* auto/pwm registers */
+	lm93_read_block(client, 10, (u8 *)(&data->block10));
+
+	lm93_update_client_common(data, client);
+}
+
+/* update routine which uses SMBus byte/word data commands only */
+static void lm93_update_client_min(struct lm93_data *data,
+				   struct i2c_client *client)
+{
+	int i,j;
+	u8 *ptr;
+
+	dev_dbg(&client->dev,"starting device update (block data disabled)\n");
+
+	/* in1 - in16: values & limits */
+	for (i = 0; i < 16; i++) {
+		data->block3[i] =
+			lm93_read_byte(client, LM93_REG_IN(i));
+		data->block7[i].min =
+			lm93_read_byte(client, LM93_REG_IN_MIN(i));
+		data->block7[i].max =
+			lm93_read_byte(client, LM93_REG_IN_MAX(i));
+	}
+
+	/* temp1 - temp4: values */
+	for (i = 0; i < 4; i++) {
+		data->block2[i] =
+			lm93_read_byte(client, LM93_REG_TEMP(i));
+	}
+
+	/* prochot1 - prochot2: values */
+	for (i = 0; i < 2; i++) {
+		data->block4[i].cur =
+			lm93_read_byte(client, LM93_REG_PROCHOT_CUR(i));
+		data->block4[i].avg =
+			lm93_read_byte(client, LM93_REG_PROCHOT_AVG(i));
+	}
+
+	/* fan1 - fan4: values & limits */
+	for (i = 0; i < 4; i++) {
+		data->block5[i] =
+			lm93_read_word(client, LM93_REG_FAN(i));
+		data->block8[i] =
+			lm93_read_word(client, LM93_REG_FAN_MIN(i));
+	}
+
+	/* pwm control registers */
+	for (i = 0; i < 2; i++) {
+		for (j = 0; j < 4; j++) {
+			data->block9[i][j] =
+				lm93_read_byte(client, LM93_REG_PWM_CTL(i,j));
+		}
+	}
+
+	/* alarm values */
+	for (i = 0, ptr = (u8 *)(&data->block1); i < 8; i++) {
+		*(ptr + i) =
+			lm93_read_byte(client, LM93_REG_HOST_ERROR_1 + i);
+	}
+
+	/* auto/pwm (base temp) registers */
+	for (i = 0; i < 4; i++) {
+		data->block10.base[i] =
+			lm93_read_byte(client, LM93_REG_TEMP_BASE(i));
+	}
+
+	/* auto/pwm (offset temp) registers */
+	for (i = 0; i < 12; i++) {
+		data->block10.offset[i] =
+			lm93_read_byte(client, LM93_REG_TEMP_OFFSET(i));
+	}
+
+	lm93_update_client_common(data, client);
+}
+
+/* following are the sysfs callback functions */
+static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf, "%d\n", LM93_IN_FROM_REG(nr, data->block3[nr]));
+}
+
+static SENSOR_DEVICE_ATTR(in1_input, S_IRUGO, show_in, NULL, 0);
+static SENSOR_DEVICE_ATTR(in2_input, S_IRUGO, show_in, NULL, 1);
+static SENSOR_DEVICE_ATTR(in3_input, S_IRUGO, show_in, NULL, 2);
+static SENSOR_DEVICE_ATTR(in4_input, S_IRUGO, show_in, NULL, 3);
+static SENSOR_DEVICE_ATTR(in5_input, S_IRUGO, show_in, NULL, 4);
+static SENSOR_DEVICE_ATTR(in6_input, S_IRUGO, show_in, NULL, 5);
+static SENSOR_DEVICE_ATTR(in7_input, S_IRUGO, show_in, NULL, 6);
+static SENSOR_DEVICE_ATTR(in8_input, S_IRUGO, show_in, NULL, 7);
+static SENSOR_DEVICE_ATTR(in9_input, S_IRUGO, show_in, NULL, 8);
+static SENSOR_DEVICE_ATTR(in10_input, S_IRUGO, show_in, NULL, 9);
+static SENSOR_DEVICE_ATTR(in11_input, S_IRUGO, show_in, NULL, 10);
+static SENSOR_DEVICE_ATTR(in12_input, S_IRUGO, show_in, NULL, 11);
+static SENSOR_DEVICE_ATTR(in13_input, S_IRUGO, show_in, NULL, 12);
+static SENSOR_DEVICE_ATTR(in14_input, S_IRUGO, show_in, NULL, 13);
+static SENSOR_DEVICE_ATTR(in15_input, S_IRUGO, show_in, NULL, 14);
+static SENSOR_DEVICE_ATTR(in16_input, S_IRUGO, show_in, NULL, 15);
+
+static ssize_t show_in_min(struct device *dev,
+			struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	int vccp = nr - 6;
+	long rc, vid;
+
+	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+		vid = LM93_VID_FROM_REG(data->vid[vccp]);
+		rc = LM93_IN_MIN_FROM_REG(data->vccp_limits[vccp], vid);
+	}
+	else {
+		rc = LM93_IN_FROM_REG(nr, data->block7[nr].min); \
+	}
+	return sprintf(buf, "%ld\n", rc); \
+}
+
+static ssize_t store_in_min(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	int vccp = nr - 6;
+	long vid;
+
+	mutex_lock(&data->update_lock);
+	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+		vid = LM93_VID_FROM_REG(data->vid[vccp]);
+		data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0xf0) |
+				LM93_IN_REL_TO_REG(val, 0, vid);
+		lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp),
+				data->vccp_limits[vccp]);
+	}
+	else {
+		data->block7[nr].min = LM93_IN_TO_REG(nr,val);
+		lm93_write_byte(client, LM93_REG_IN_MIN(nr),
+				data->block7[nr].min);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(in1_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 0);
+static SENSOR_DEVICE_ATTR(in2_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 1);
+static SENSOR_DEVICE_ATTR(in3_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 2);
+static SENSOR_DEVICE_ATTR(in4_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 3);
+static SENSOR_DEVICE_ATTR(in5_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 4);
+static SENSOR_DEVICE_ATTR(in6_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 5);
+static SENSOR_DEVICE_ATTR(in7_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 6);
+static SENSOR_DEVICE_ATTR(in8_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 7);
+static SENSOR_DEVICE_ATTR(in9_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 8);
+static SENSOR_DEVICE_ATTR(in10_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 9);
+static SENSOR_DEVICE_ATTR(in11_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 10);
+static SENSOR_DEVICE_ATTR(in12_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 11);
+static SENSOR_DEVICE_ATTR(in13_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 12);
+static SENSOR_DEVICE_ATTR(in14_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 13);
+static SENSOR_DEVICE_ATTR(in15_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 14);
+static SENSOR_DEVICE_ATTR(in16_min, S_IWUSR | S_IRUGO,
+			  show_in_min, store_in_min, 15);
+
+static ssize_t show_in_max(struct device *dev,
+			   struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	int vccp = nr - 6;
+	long rc, vid;
+
+	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+		vid = LM93_VID_FROM_REG(data->vid[vccp]);
+		rc = LM93_IN_MAX_FROM_REG(data->vccp_limits[vccp],vid);
+	}
+	else {
+		rc = LM93_IN_FROM_REG(nr,data->block7[nr].max); \
+	}
+	return sprintf(buf,"%ld\n",rc); \
+}
+
+static ssize_t store_in_max(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	int vccp = nr - 6;
+	long vid;
+
+	mutex_lock(&data->update_lock);
+	if ((nr==6 || nr==7) && (vccp_limit_type[vccp])) {
+		vid = LM93_VID_FROM_REG(data->vid[vccp]);
+		data->vccp_limits[vccp] = (data->vccp_limits[vccp] & 0x0f) |
+				LM93_IN_REL_TO_REG(val, 1, vid);
+		lm93_write_byte(client, LM93_REG_VCCP_LIMIT_OFF(vccp),
+				data->vccp_limits[vccp]);
+	}
+	else {
+		data->block7[nr].max = LM93_IN_TO_REG(nr,val);
+		lm93_write_byte(client, LM93_REG_IN_MAX(nr),
+				data->block7[nr].max);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(in1_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 0);
+static SENSOR_DEVICE_ATTR(in2_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 1);
+static SENSOR_DEVICE_ATTR(in3_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 2);
+static SENSOR_DEVICE_ATTR(in4_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 3);
+static SENSOR_DEVICE_ATTR(in5_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 4);
+static SENSOR_DEVICE_ATTR(in6_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 5);
+static SENSOR_DEVICE_ATTR(in7_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 6);
+static SENSOR_DEVICE_ATTR(in8_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 7);
+static SENSOR_DEVICE_ATTR(in9_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 8);
+static SENSOR_DEVICE_ATTR(in10_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 9);
+static SENSOR_DEVICE_ATTR(in11_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 10);
+static SENSOR_DEVICE_ATTR(in12_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 11);
+static SENSOR_DEVICE_ATTR(in13_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 12);
+static SENSOR_DEVICE_ATTR(in14_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 13);
+static SENSOR_DEVICE_ATTR(in15_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 14);
+static SENSOR_DEVICE_ATTR(in16_max, S_IWUSR | S_IRUGO,
+			  show_in_max, store_in_max, 15);
+
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->block2[nr]));
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2);
+
+static ssize_t show_temp_min(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->temp_lim[nr].min));
+}
+
+static ssize_t store_temp_min(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp_lim[nr].min = LM93_TEMP_TO_REG(val);
+	lm93_write_byte(client, LM93_REG_TEMP_MIN(nr), data->temp_lim[nr].min);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO,
+			  show_temp_min, store_temp_min, 0);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO,
+			  show_temp_min, store_temp_min, 1);
+static SENSOR_DEVICE_ATTR(temp3_min, S_IWUSR | S_IRUGO,
+			  show_temp_min, store_temp_min, 2);
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->temp_lim[nr].max));
+}
+
+static ssize_t store_temp_max(struct device *dev, struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp_lim[nr].max = LM93_TEMP_TO_REG(val);
+	lm93_write_byte(client, LM93_REG_TEMP_MAX(nr), data->temp_lim[nr].max);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO,
+			  show_temp_max, store_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO,
+			  show_temp_max, store_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp3_max, S_IWUSR | S_IRUGO,
+			  show_temp_max, store_temp_max, 2);
+
+static ssize_t show_temp_auto_base(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->block10.base[nr]));
+}
+
+static ssize_t store_temp_auto_base(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->block10.base[nr] = LM93_TEMP_TO_REG(val);
+	lm93_write_byte(client, LM93_REG_TEMP_BASE(nr), data->block10.base[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_auto_base, S_IWUSR | S_IRUGO,
+			  show_temp_auto_base, store_temp_auto_base, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_base, S_IWUSR | S_IRUGO,
+			  show_temp_auto_base, store_temp_auto_base, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_base, S_IWUSR | S_IRUGO,
+			  show_temp_auto_base, store_temp_auto_base, 2);
+
+static ssize_t show_temp_auto_boost(struct device *dev,
+				    struct device_attribute *attr,char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_TEMP_FROM_REG(data->boost[nr]));
+}
+
+static ssize_t store_temp_auto_boost(struct device *dev,
+				     struct device_attribute *attr,
+				     const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->boost[nr] = LM93_TEMP_TO_REG(val);
+	lm93_write_byte(client, LM93_REG_BOOST(nr), data->boost[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_auto_boost, S_IWUSR | S_IRUGO,
+			  show_temp_auto_boost, store_temp_auto_boost, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_boost, S_IWUSR | S_IRUGO,
+			  show_temp_auto_boost, store_temp_auto_boost, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_boost, S_IWUSR | S_IRUGO,
+			  show_temp_auto_boost, store_temp_auto_boost, 2);
+
+static ssize_t show_temp_auto_boost_hyst(struct device *dev,
+					 struct device_attribute *attr,
+					 char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr);
+	return sprintf(buf,"%d\n",
+		       LM93_AUTO_BOOST_HYST_FROM_REGS(data, nr, mode));
+}
+
+static ssize_t store_temp_auto_boost_hyst(struct device *dev,
+					  struct device_attribute *attr,
+					  const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	/* force 0.5C/bit mode */
+	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);
+	data->sfc2 |= ((nr < 2) ? 0x10 : 0x20);
+	lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
+	data->boost_hyst[nr/2] = LM93_AUTO_BOOST_HYST_TO_REG(data, val, nr, 1);
+	lm93_write_byte(client, LM93_REG_BOOST_HYST(nr),
+			data->boost_hyst[nr/2]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_auto_boost_hyst, S_IWUSR | S_IRUGO,
+			  show_temp_auto_boost_hyst,
+			  store_temp_auto_boost_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_boost_hyst, S_IWUSR | S_IRUGO,
+			  show_temp_auto_boost_hyst,
+			  store_temp_auto_boost_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_boost_hyst, S_IWUSR | S_IRUGO,
+			  show_temp_auto_boost_hyst,
+			  store_temp_auto_boost_hyst, 2);
+
+static ssize_t show_temp_auto_offset(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
+	int nr = s_attr->index;
+	int ofs = s_attr->nr;
+	struct lm93_data *data = lm93_update_device(dev);
+	int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr);
+	return sprintf(buf,"%d\n",
+	       LM93_TEMP_AUTO_OFFSET_FROM_REG(data->block10.offset[ofs],
+					      nr,mode));
+}
+
+static ssize_t store_temp_auto_offset(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct sensor_device_attribute_2 *s_attr = to_sensor_dev_attr_2(attr);
+	int nr = s_attr->index;
+	int ofs = s_attr->nr;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	/* force 0.5C/bit mode */
+	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);
+	data->sfc2 |= ((nr < 2) ? 0x10 : 0x20);
+	lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
+	data->block10.offset[ofs] = LM93_TEMP_AUTO_OFFSET_TO_REG(
+			data->block10.offset[ofs], val, nr, 1);
+	lm93_write_byte(client, LM93_REG_TEMP_OFFSET(ofs),
+			data->block10.offset[ofs]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset1, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 0, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset2, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 1, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset3, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 2, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset4, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 3, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset5, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 4, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset6, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 5, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset7, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 6, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset8, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 7, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset9, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 8, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset10, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 9, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset11, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 10, 0);
+static SENSOR_DEVICE_ATTR_2(temp1_auto_offset12, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 11, 0);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset1, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 0, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset2, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 1, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset3, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 2, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset4, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 3, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset5, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 4, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset6, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 5, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset7, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 6, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset8, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 7, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset9, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 8, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset10, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 9, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset11, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 10, 1);
+static SENSOR_DEVICE_ATTR_2(temp2_auto_offset12, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 11, 1);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset1, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 0, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset2, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 1, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset3, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 2, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset4, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 3, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset5, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 4, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset6, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 5, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset7, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 6, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset8, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 7, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset9, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 8, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset10, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 9, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset11, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 10, 2);
+static SENSOR_DEVICE_ATTR_2(temp3_auto_offset12, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset, store_temp_auto_offset, 11, 2);
+
+static ssize_t show_temp_auto_pwm_min(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	u8 reg, ctl4;
+	struct lm93_data *data = lm93_update_device(dev);
+	reg = data->auto_pwm_min_hyst[nr/2] >> 4 & 0x0f;
+	ctl4 = data->block9[nr][LM93_PWM_CTL4];
+	return sprintf(buf,"%d\n",LM93_PWM_FROM_REG(reg, (ctl4 & 0x07) ?
+				LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ));
+}
+
+static ssize_t store_temp_auto_pwm_min(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 reg, ctl4;
+
+	mutex_lock(&data->update_lock);
+	reg = lm93_read_byte(client, LM93_REG_PWM_MIN_HYST(nr));
+	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4));
+	reg = (reg & 0x0f) |
+		LM93_PWM_TO_REG(val, (ctl4 & 0x07) ?
+				LM93_PWM_MAP_LO_FREQ :
+				LM93_PWM_MAP_HI_FREQ) << 4;
+	data->auto_pwm_min_hyst[nr/2] = reg;
+	lm93_write_byte(client, LM93_REG_PWM_MIN_HYST(nr), reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_auto_pwm_min, S_IWUSR | S_IRUGO,
+			  show_temp_auto_pwm_min,
+			  store_temp_auto_pwm_min, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_pwm_min, S_IWUSR | S_IRUGO,
+			  show_temp_auto_pwm_min,
+			  store_temp_auto_pwm_min, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_pwm_min, S_IWUSR | S_IRUGO,
+			  show_temp_auto_pwm_min,
+			  store_temp_auto_pwm_min, 2);
+
+static ssize_t show_temp_auto_offset_hyst(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	int mode = LM93_TEMP_OFFSET_MODE_FROM_REG(data->sfc2, nr);
+	return sprintf(buf,"%d\n",LM93_TEMP_OFFSET_FROM_REG(
+					data->auto_pwm_min_hyst[nr/2], mode));
+}
+
+static ssize_t store_temp_auto_offset_hyst(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 reg;
+
+	mutex_lock(&data->update_lock);
+	/* force 0.5C/bit mode */
+	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);
+	data->sfc2 |= ((nr < 2) ? 0x10 : 0x20);
+	lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
+	reg = data->auto_pwm_min_hyst[nr/2];
+	reg = (reg & 0xf0) | (LM93_TEMP_OFFSET_TO_REG(val, 1) & 0x0f);
+	data->auto_pwm_min_hyst[nr/2] = reg;
+	lm93_write_byte(client, LM93_REG_PWM_MIN_HYST(nr), reg);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_auto_offset_hyst, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset_hyst,
+			  store_temp_auto_offset_hyst, 0);
+static SENSOR_DEVICE_ATTR(temp2_auto_offset_hyst, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset_hyst,
+			  store_temp_auto_offset_hyst, 1);
+static SENSOR_DEVICE_ATTR(temp3_auto_offset_hyst, S_IWUSR | S_IRUGO,
+			  show_temp_auto_offset_hyst,
+			  store_temp_auto_offset_hyst, 2);
+
+static ssize_t show_fan_input(struct device *dev,
+		struct device_attribute *attr, char *buf)
+{
+	struct sensor_device_attribute *s_attr = to_sensor_dev_attr(attr);
+	int nr = s_attr->index;
+	struct lm93_data *data = lm93_update_device(dev);
+
+	return sprintf(buf,"%d\n",LM93_FAN_FROM_REG(data->block5[nr]));
+}
+
+static SENSOR_DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0);
+static SENSOR_DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1);
+static SENSOR_DEVICE_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2);
+static SENSOR_DEVICE_ATTR(fan4_input, S_IRUGO, show_fan_input, NULL, 3);
+
+static ssize_t show_fan_min(struct device *dev,
+			      struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+
+	return sprintf(buf,"%d\n",LM93_FAN_FROM_REG(data->block8[nr]));
+}
+
+static ssize_t store_fan_min(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->block8[nr] = LM93_FAN_TO_REG(val);
+	lm93_write_word(client,LM93_REG_FAN_MIN(nr),data->block8[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, store_fan_min, 0);
+static SENSOR_DEVICE_ATTR(fan2_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, store_fan_min, 1);
+static SENSOR_DEVICE_ATTR(fan3_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, store_fan_min, 2);
+static SENSOR_DEVICE_ATTR(fan4_min, S_IWUSR | S_IRUGO,
+			  show_fan_min, store_fan_min, 3);
+
+/* some tedious bit-twiddling here to deal with the register format:
+
+	data->sf_tach_to_pwm: (tach to pwm mapping bits)
+
+		bit |  7  |  6  |  5  |  4  |  3  |  2  |  1  |  0
+		     T4:P2 T4:P1 T3:P2 T3:P1 T2:P2 T2:P1 T1:P2 T1:P1
+
+	data->sfc2: (enable bits)
+
+		bit |  3  |  2  |  1  |  0
+		       T4    T3    T2    T1
+*/
+
+static ssize_t show_fan_smart_tach(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	long rc = 0;
+	int mapping;
+
+	/* extract the relevant mapping */
+	mapping = (data->sf_tach_to_pwm >> (nr * 2)) & 0x03;
+
+	/* if there's a mapping and it's enabled */
+	if (mapping && ((data->sfc2 >> nr) & 0x01))
+		rc = mapping;
+	return sprintf(buf,"%ld\n",rc);
+}
+
+/* helper function - must grab data->update_lock before calling
+   fan is 0-3, indicating fan1-fan4 */
+static void lm93_write_fan_smart_tach(struct i2c_client *client,
+	struct lm93_data *data, int fan, long value)
+{
+	/* insert the new mapping and write it out */
+	data->sf_tach_to_pwm = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM);
+	data->sf_tach_to_pwm &= ~(0x3 << fan * 2);
+	data->sf_tach_to_pwm |= value << fan * 2;
+	lm93_write_byte(client, LM93_REG_SF_TACH_TO_PWM, data->sf_tach_to_pwm);
+
+	/* insert the enable bit and write it out */
+	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);
+	if (value)
+		data->sfc2 |= 1 << fan;
+	else
+		data->sfc2 &= ~(1 << fan);
+	lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
+}
+
+static ssize_t store_fan_smart_tach(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	/* sanity test, ignore the write otherwise */
+	if (0 <= val && val <= 2) {
+		/* can't enable if pwm freq is 22.5KHz */
+		if (val) {
+			u8 ctl4 = lm93_read_byte(client,
+				LM93_REG_PWM_CTL(val-1,LM93_PWM_CTL4));
+			if ((ctl4 & 0x07) == 0)
+				val = 0;
+		}
+		lm93_write_fan_smart_tach(client, data, nr, val);
+	}
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(fan1_smart_tach, S_IWUSR | S_IRUGO,
+			  show_fan_smart_tach, store_fan_smart_tach, 0);
+static SENSOR_DEVICE_ATTR(fan2_smart_tach, S_IWUSR | S_IRUGO,
+			  show_fan_smart_tach, store_fan_smart_tach, 1);
+static SENSOR_DEVICE_ATTR(fan3_smart_tach, S_IWUSR | S_IRUGO,
+			  show_fan_smart_tach, store_fan_smart_tach, 2);
+static SENSOR_DEVICE_ATTR(fan4_smart_tach, S_IWUSR | S_IRUGO,
+			  show_fan_smart_tach, store_fan_smart_tach, 3);
+
+static ssize_t show_pwm(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	u8 ctl2, ctl4;
+	long rc;
+
+	ctl2 = data->block9[nr][LM93_PWM_CTL2];
+	ctl4 = data->block9[nr][LM93_PWM_CTL4];
+	if (ctl2 & 0x01) /* show user commanded value if enabled */
+		rc = data->pwm_override[nr];
+	else /* show present h/w value if manual pwm disabled */
+		rc = LM93_PWM_FROM_REG(ctl2 >> 4, (ctl4 & 0x07) ?
+			LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ);
+	return sprintf(buf,"%ld\n",rc);
+}
+
+static ssize_t store_pwm(struct device *dev, struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ctl2, ctl4;
+
+	mutex_lock(&data->update_lock);
+	ctl2 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2));
+	ctl4 = lm93_read_byte(client, LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4));
+	ctl2 = (ctl2 & 0x0f) | LM93_PWM_TO_REG(val,(ctl4 & 0x07) ?
+			LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ) << 4;
+	/* save user commanded value */
+	data->pwm_override[nr] = LM93_PWM_FROM_REG(ctl2 >> 4,
+			(ctl4 & 0x07) ?  LM93_PWM_MAP_LO_FREQ :
+			LM93_PWM_MAP_HI_FREQ);
+	lm93_write_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2),ctl2);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 0);
+static SENSOR_DEVICE_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, store_pwm, 1);
+
+static ssize_t show_pwm_enable(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	u8 ctl2;
+	long rc;
+
+	ctl2 = data->block9[nr][LM93_PWM_CTL2];
+	if (ctl2 & 0x01) /* manual override enabled ? */
+		rc = ((ctl2 & 0xF0) == 0xF0) ? 0 : 1;
+	else
+		rc = 2;
+	return sprintf(buf,"%ld\n",rc);
+}
+
+static ssize_t store_pwm_enable(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ctl2;
+
+	mutex_lock(&data->update_lock);
+	ctl2 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2));
+
+	switch (val) {
+	case 0:
+		ctl2 |= 0xF1; /* enable manual override, set PWM to max */
+		break;
+	case 1: ctl2 |= 0x01; /* enable manual override */
+		break;
+	case 2: ctl2 &= ~0x01; /* disable manual override */
+		break;
+	default:
+		mutex_unlock(&data->update_lock);
+		return -EINVAL;
+	}
+
+	lm93_write_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL2),ctl2);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_enable, S_IWUSR | S_IRUGO,
+				show_pwm_enable, store_pwm_enable, 0);
+static SENSOR_DEVICE_ATTR(pwm2_enable, S_IWUSR | S_IRUGO,
+				show_pwm_enable, store_pwm_enable, 1);
+
+static ssize_t show_pwm_freq(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	u8 ctl4;
+
+	ctl4 = data->block9[nr][LM93_PWM_CTL4];
+	return sprintf(buf,"%d\n",LM93_PWM_FREQ_FROM_REG(ctl4));
+}
+
+/* helper function - must grab data->update_lock before calling
+   pwm is 0-1, indicating pwm1-pwm2
+   this disables smart tach for all tach channels bound to the given pwm */
+static void lm93_disable_fan_smart_tach(struct i2c_client *client,
+	struct lm93_data *data, int pwm)
+{
+	int mapping = lm93_read_byte(client, LM93_REG_SF_TACH_TO_PWM);
+	int mask;
+
+	/* collapse the mapping into a mask of enable bits */
+	mapping = (mapping >> pwm) & 0x55;
+	mask = mapping & 0x01;
+	mask |= (mapping & 0x04) >> 1;
+	mask |= (mapping & 0x10) >> 2;
+	mask |= (mapping & 0x40) >> 3;
+
+	/* disable smart tach according to the mask */
+	data->sfc2 = lm93_read_byte(client, LM93_REG_SFC2);
+	data->sfc2 &= ~mask;
+	lm93_write_byte(client, LM93_REG_SFC2, data->sfc2);
+}
+
+static ssize_t store_pwm_freq(struct device *dev,
+				struct device_attribute *attr,
+				const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ctl4;
+
+	mutex_lock(&data->update_lock);
+	ctl4 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4));
+	ctl4 = (ctl4 & 0xf8) | LM93_PWM_FREQ_TO_REG(val);
+	data->block9[nr][LM93_PWM_CTL4] = ctl4;
+	/* ctl4 == 0 -> 22.5KHz -> disable smart tach */
+	if (!ctl4)
+		lm93_disable_fan_smart_tach(client, data, nr);
+	lm93_write_byte(client,	LM93_REG_PWM_CTL(nr,LM93_PWM_CTL4), ctl4);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_freq, S_IWUSR | S_IRUGO,
+			  show_pwm_freq, store_pwm_freq, 0);
+static SENSOR_DEVICE_ATTR(pwm2_freq, S_IWUSR | S_IRUGO,
+			  show_pwm_freq, store_pwm_freq, 1);
+
+static ssize_t show_pwm_auto_channels(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",data->block9[nr][LM93_PWM_CTL1]);
+}
+
+static ssize_t store_pwm_auto_channels(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->block9[nr][LM93_PWM_CTL1] = SENSORS_LIMIT(val, 0, 255);
+	lm93_write_byte(client,	LM93_REG_PWM_CTL(nr,LM93_PWM_CTL1),
+				data->block9[nr][LM93_PWM_CTL1]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_auto_channels, S_IWUSR | S_IRUGO,
+			  show_pwm_auto_channels, store_pwm_auto_channels, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_channels, S_IWUSR | S_IRUGO,
+			  show_pwm_auto_channels, store_pwm_auto_channels, 1);
+
+static ssize_t show_pwm_auto_spinup_min(struct device *dev,
+				struct device_attribute *attr,char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	u8 ctl3, ctl4;
+
+	ctl3 = data->block9[nr][LM93_PWM_CTL3];
+	ctl4 = data->block9[nr][LM93_PWM_CTL4];
+	return sprintf(buf,"%d\n",
+		       LM93_PWM_FROM_REG(ctl3 & 0x0f, (ctl4 & 0x07) ?
+			LM93_PWM_MAP_LO_FREQ : LM93_PWM_MAP_HI_FREQ));
+}
+
+static ssize_t store_pwm_auto_spinup_min(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ctl3, ctl4;
+
+	mutex_lock(&data->update_lock);
+	ctl3 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3));
+	ctl4 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL4));
+	ctl3 = (ctl3 & 0xf0) | 	LM93_PWM_TO_REG(val, (ctl4 & 0x07) ?
+			LM93_PWM_MAP_LO_FREQ :
+			LM93_PWM_MAP_HI_FREQ);
+	data->block9[nr][LM93_PWM_CTL3] = ctl3;
+	lm93_write_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_min, S_IWUSR | S_IRUGO,
+			  show_pwm_auto_spinup_min,
+			  store_pwm_auto_spinup_min, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_min, S_IWUSR | S_IRUGO,
+			  show_pwm_auto_spinup_min,
+			  store_pwm_auto_spinup_min, 1);
+
+static ssize_t show_pwm_auto_spinup_time(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_SPINUP_TIME_FROM_REG(
+				data->block9[nr][LM93_PWM_CTL3]));
+}
+
+static ssize_t store_pwm_auto_spinup_time(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ctl3;
+
+	mutex_lock(&data->update_lock);
+	ctl3 = lm93_read_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3));
+	ctl3 = (ctl3 & 0x1f) | (LM93_SPINUP_TIME_TO_REG(val) << 5 & 0xe0);
+	data->block9[nr][LM93_PWM_CTL3] = ctl3;
+	lm93_write_byte(client,LM93_REG_PWM_CTL(nr, LM93_PWM_CTL3), ctl3);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(pwm1_auto_spinup_time, S_IWUSR | S_IRUGO,
+			  show_pwm_auto_spinup_time,
+			  store_pwm_auto_spinup_time, 0);
+static SENSOR_DEVICE_ATTR(pwm2_auto_spinup_time, S_IWUSR | S_IRUGO,
+			  show_pwm_auto_spinup_time,
+			  store_pwm_auto_spinup_time, 1);
+
+static ssize_t show_pwm_auto_prochot_ramp(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",
+		       LM93_RAMP_FROM_REG(data->pwm_ramp_ctl >> 4 & 0x0f));
+}
+
+static ssize_t store_pwm_auto_prochot_ramp(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ramp;
+
+	mutex_lock(&data->update_lock);
+	ramp = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL);
+	ramp = (ramp & 0x0f) | (LM93_RAMP_TO_REG(val) << 4 & 0xf0);
+	lm93_write_byte(client, LM93_REG_PWM_RAMP_CTL, ramp);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static DEVICE_ATTR(pwm_auto_prochot_ramp, S_IRUGO | S_IWUSR,
+			show_pwm_auto_prochot_ramp,
+			store_pwm_auto_prochot_ramp);
+
+static ssize_t show_pwm_auto_vrdhot_ramp(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",
+		       LM93_RAMP_FROM_REG(data->pwm_ramp_ctl & 0x0f));
+}
+
+static ssize_t store_pwm_auto_vrdhot_ramp(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 ramp;
+
+	mutex_lock(&data->update_lock);
+	ramp = lm93_read_byte(client, LM93_REG_PWM_RAMP_CTL);
+	ramp = (ramp & 0xf0) | (LM93_RAMP_TO_REG(val) & 0x0f);
+	lm93_write_byte(client, LM93_REG_PWM_RAMP_CTL, ramp);
+	mutex_unlock(&data->update_lock);
+	return 0;
+}
+
+static DEVICE_ATTR(pwm_auto_vrdhot_ramp, S_IRUGO | S_IWUSR,
+			show_pwm_auto_vrdhot_ramp,
+			store_pwm_auto_vrdhot_ramp);
+
+static ssize_t show_vid(struct device *dev, struct device_attribute *attr,
+			char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_VID_FROM_REG(data->vid[nr]));
+}
+
+static SENSOR_DEVICE_ATTR(vid1, S_IRUGO, show_vid, NULL, 0);
+static SENSOR_DEVICE_ATTR(vid2, S_IRUGO, show_vid, NULL, 1);
+
+static ssize_t show_prochot(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",data->block4[nr].cur);
+}
+
+static SENSOR_DEVICE_ATTR(prochot1, S_IRUGO, show_prochot, NULL, 0);
+static SENSOR_DEVICE_ATTR(prochot2, S_IRUGO, show_prochot, NULL, 1);
+
+static ssize_t show_prochot_avg(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",data->block4[nr].avg);
+}
+
+static SENSOR_DEVICE_ATTR(prochot1_avg, S_IRUGO, show_prochot_avg, NULL, 0);
+static SENSOR_DEVICE_ATTR(prochot2_avg, S_IRUGO, show_prochot_avg, NULL, 1);
+
+static ssize_t show_prochot_max(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",data->prochot_max[nr]);
+}
+
+static ssize_t store_prochot_max(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->prochot_max[nr] = LM93_PROCHOT_TO_REG(val);
+	lm93_write_byte(client, LM93_REG_PROCHOT_MAX(nr),
+			data->prochot_max[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(prochot1_max, S_IWUSR | S_IRUGO,
+			  show_prochot_max, store_prochot_max, 0);
+static SENSOR_DEVICE_ATTR(prochot2_max, S_IWUSR | S_IRUGO,
+			  show_prochot_max, store_prochot_max, 1);
+
+static const u8 prochot_override_mask[] = { 0x80, 0x40 };
+
+static ssize_t show_prochot_override(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",
+		(data->prochot_override & prochot_override_mask[nr]) ? 1 : 0);
+}
+
+static ssize_t store_prochot_override(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	if (val)
+		data->prochot_override |= prochot_override_mask[nr];
+	else
+		data->prochot_override &= (~prochot_override_mask[nr]);
+	lm93_write_byte(client, LM93_REG_PROCHOT_OVERRIDE,
+			data->prochot_override);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(prochot1_override, S_IWUSR | S_IRUGO,
+			  show_prochot_override, store_prochot_override, 0);
+static SENSOR_DEVICE_ATTR(prochot2_override, S_IWUSR | S_IRUGO,
+			  show_prochot_override, store_prochot_override, 1);
+
+static ssize_t show_prochot_interval(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	u8 tmp;
+	if (nr==1)
+		tmp = (data->prochot_interval & 0xf0) >> 4;
+	else
+		tmp = data->prochot_interval & 0x0f;
+	return sprintf(buf,"%d\n",LM93_INTERVAL_FROM_REG(tmp));
+}
+
+static ssize_t store_prochot_interval(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+	u8 tmp;
+
+	mutex_lock(&data->update_lock);
+	tmp = lm93_read_byte(client, LM93_REG_PROCHOT_INTERVAL);
+	if (nr==1)
+		tmp = (tmp & 0x0f) | (LM93_INTERVAL_TO_REG(val) << 4);
+	else
+		tmp = (tmp & 0xf0) | LM93_INTERVAL_TO_REG(val);
+	data->prochot_interval = tmp;
+	lm93_write_byte(client, LM93_REG_PROCHOT_INTERVAL, tmp);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(prochot1_interval, S_IWUSR | S_IRUGO,
+			  show_prochot_interval, store_prochot_interval, 0);
+static SENSOR_DEVICE_ATTR(prochot2_interval, S_IWUSR | S_IRUGO,
+			  show_prochot_interval, store_prochot_interval, 1);
+
+static ssize_t show_prochot_override_duty_cycle(struct device *dev,
+						struct device_attribute *attr,
+						char *buf)
+{
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",data->prochot_override & 0x0f);
+}
+
+static ssize_t store_prochot_override_duty_cycle(struct device *dev,
+						struct device_attribute *attr,
+						const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->prochot_override = (data->prochot_override & 0xf0) |
+					SENSORS_LIMIT(val, 0, 15);
+	lm93_write_byte(client, LM93_REG_PROCHOT_OVERRIDE,
+			data->prochot_override);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static DEVICE_ATTR(prochot_override_duty_cycle, S_IRUGO | S_IWUSR,
+			show_prochot_override_duty_cycle,
+			store_prochot_override_duty_cycle);
+
+static ssize_t show_prochot_short(struct device *dev,
+				struct device_attribute *attr, char *buf)
+{
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",(data->config & 0x10) ? 1 : 0);
+}
+
+static ssize_t store_prochot_short(struct device *dev,
+					struct device_attribute *attr,
+					const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm93_data *data = i2c_get_clientdata(client);
+	u32 val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	if (val)
+		data->config |= 0x10;
+	else
+		data->config &= ~0x10;
+	lm93_write_byte(client, LM93_REG_CONFIG, data->config);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static DEVICE_ATTR(prochot_short, S_IRUGO | S_IWUSR,
+		   show_prochot_short, store_prochot_short);
+
+static ssize_t show_vrdhot(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	int nr = (to_sensor_dev_attr(attr))->index;
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",
+		       data->block1.host_status_1 & (1 << (nr+4)) ? 1 : 0);
+}
+
+static SENSOR_DEVICE_ATTR(vrdhot1, S_IRUGO, show_vrdhot, NULL, 0);
+static SENSOR_DEVICE_ATTR(vrdhot2, S_IRUGO, show_vrdhot, NULL, 1);
+
+static ssize_t show_gpio(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_GPI_FROM_REG(data->gpi));
+}
+
+static DEVICE_ATTR(gpio, S_IRUGO, show_gpio, NULL);
+
+static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
+				char *buf)
+{
+	struct lm93_data *data = lm93_update_device(dev);
+	return sprintf(buf,"%d\n",LM93_ALARMS_FROM_REG(data->block1));
+}
+
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+
+static struct attribute *lm93_attrs[] = {
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in5_input.dev_attr.attr,
+	&sensor_dev_attr_in6_input.dev_attr.attr,
+	&sensor_dev_attr_in7_input.dev_attr.attr,
+	&sensor_dev_attr_in8_input.dev_attr.attr,
+	&sensor_dev_attr_in9_input.dev_attr.attr,
+	&sensor_dev_attr_in10_input.dev_attr.attr,
+	&sensor_dev_attr_in11_input.dev_attr.attr,
+	&sensor_dev_attr_in12_input.dev_attr.attr,
+	&sensor_dev_attr_in13_input.dev_attr.attr,
+	&sensor_dev_attr_in14_input.dev_attr.attr,
+	&sensor_dev_attr_in15_input.dev_attr.attr,
+	&sensor_dev_attr_in16_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in5_min.dev_attr.attr,
+	&sensor_dev_attr_in6_min.dev_attr.attr,
+	&sensor_dev_attr_in7_min.dev_attr.attr,
+	&sensor_dev_attr_in8_min.dev_attr.attr,
+	&sensor_dev_attr_in9_min.dev_attr.attr,
+	&sensor_dev_attr_in10_min.dev_attr.attr,
+	&sensor_dev_attr_in11_min.dev_attr.attr,
+	&sensor_dev_attr_in12_min.dev_attr.attr,
+	&sensor_dev_attr_in13_min.dev_attr.attr,
+	&sensor_dev_attr_in14_min.dev_attr.attr,
+	&sensor_dev_attr_in15_min.dev_attr.attr,
+	&sensor_dev_attr_in16_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+	&sensor_dev_attr_in5_max.dev_attr.attr,
+	&sensor_dev_attr_in6_max.dev_attr.attr,
+	&sensor_dev_attr_in7_max.dev_attr.attr,
+	&sensor_dev_attr_in8_max.dev_attr.attr,
+	&sensor_dev_attr_in9_max.dev_attr.attr,
+	&sensor_dev_attr_in10_max.dev_attr.attr,
+	&sensor_dev_attr_in11_max.dev_attr.attr,
+	&sensor_dev_attr_in12_max.dev_attr.attr,
+	&sensor_dev_attr_in13_max.dev_attr.attr,
+	&sensor_dev_attr_in14_max.dev_attr.attr,
+	&sensor_dev_attr_in15_max.dev_attr.attr,
+	&sensor_dev_attr_in16_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_base.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_base.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_base.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_boost.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_boost.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_boost.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_boost_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_boost_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_boost_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset1.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset2.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset3.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset4.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset5.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset6.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset7.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset8.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset9.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset10.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset11.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset12.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset1.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset2.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset3.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset4.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset5.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset6.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset7.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset8.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset9.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset10.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset11.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset12.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset1.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset2.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset3.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset4.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset5.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset6.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset7.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset8.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset9.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset10.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset11.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset12.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_pwm_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_pwm_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_pwm_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_auto_offset_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_auto_offset_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_auto_offset_hyst.dev_attr.attr,
+	&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,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan3_min.dev_attr.attr,
+	&sensor_dev_attr_fan4_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_smart_tach.dev_attr.attr,
+	&sensor_dev_attr_fan2_smart_tach.dev_attr.attr,
+	&sensor_dev_attr_fan3_smart_tach.dev_attr.attr,
+	&sensor_dev_attr_fan4_smart_tach.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm2.dev_attr.attr,
+	&sensor_dev_attr_pwm1_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm2_enable.dev_attr.attr,
+	&sensor_dev_attr_pwm1_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm2_freq.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_channels.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_channels.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_spinup_min.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_spinup_min.dev_attr.attr,
+	&sensor_dev_attr_pwm1_auto_spinup_time.dev_attr.attr,
+	&sensor_dev_attr_pwm2_auto_spinup_time.dev_attr.attr,
+	&dev_attr_pwm_auto_prochot_ramp.attr,
+	&dev_attr_pwm_auto_vrdhot_ramp.attr,
+	&sensor_dev_attr_vid1.dev_attr.attr,
+	&sensor_dev_attr_vid2.dev_attr.attr,
+	&sensor_dev_attr_prochot1.dev_attr.attr,
+	&sensor_dev_attr_prochot2.dev_attr.attr,
+	&sensor_dev_attr_prochot1_avg.dev_attr.attr,
+	&sensor_dev_attr_prochot2_avg.dev_attr.attr,
+	&sensor_dev_attr_prochot1_max.dev_attr.attr,
+	&sensor_dev_attr_prochot2_max.dev_attr.attr,
+	&sensor_dev_attr_prochot1_override.dev_attr.attr,
+	&sensor_dev_attr_prochot2_override.dev_attr.attr,
+	&sensor_dev_attr_prochot1_interval.dev_attr.attr,
+	&sensor_dev_attr_prochot2_interval.dev_attr.attr,
+	&dev_attr_prochot_override_duty_cycle.attr,
+	&dev_attr_prochot_short.attr,
+	&sensor_dev_attr_vrdhot1.dev_attr.attr,
+	&sensor_dev_attr_vrdhot2.dev_attr.attr,
+	&dev_attr_gpio.attr,
+	&dev_attr_alarms.attr,
+	NULL
+};
+
+static struct attribute_group lm93_attr_grp = {
+	.attrs = lm93_attrs,
+};
+
+static void lm93_init_client(struct i2c_client *client)
+{
+	int i;
+	u8 reg;
+
+	/* configure VID pin input thresholds */
+	reg = lm93_read_byte(client, LM93_REG_GPI_VID_CTL);
+	lm93_write_byte(client, LM93_REG_GPI_VID_CTL,
+			reg | (vid_agtl ? 0x03 : 0x00));
+
+	if (init) {
+		/* enable #ALERT pin */
+		reg = lm93_read_byte(client, LM93_REG_CONFIG);
+		lm93_write_byte(client, LM93_REG_CONFIG, reg | 0x08);
+
+		/* enable ASF mode for BMC status registers */
+		reg = lm93_read_byte(client, LM93_REG_STATUS_CONTROL);
+		lm93_write_byte(client, LM93_REG_STATUS_CONTROL, reg | 0x02);
+
+		/* set sleep state to S0 */
+		lm93_write_byte(client, LM93_REG_SLEEP_CONTROL, 0);
+
+		/* unmask #VRDHOT and dynamic VCCP (if nec) error events */
+		reg = lm93_read_byte(client, LM93_REG_MISC_ERR_MASK);
+		reg &= ~0x03;
+		reg &= ~(vccp_limit_type[0] ? 0x10 : 0);
+		reg &= ~(vccp_limit_type[1] ? 0x20 : 0);
+		lm93_write_byte(client, LM93_REG_MISC_ERR_MASK, reg);
+	}
+
+	/* start monitoring */
+	reg = lm93_read_byte(client, LM93_REG_CONFIG);
+	lm93_write_byte(client, LM93_REG_CONFIG, reg | 0x01);
+
+	/* spin until ready */
+	for (i=0; i<20; i++) {
+		msleep(10);
+		if ((lm93_read_byte(client, LM93_REG_CONFIG) & 0x80) == 0x80)
+			return;
+	}
+
+	dev_warn(&client->dev,"timed out waiting for sensor "
+		 "chip to signal ready!\n");
+}
+
+static int lm93_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct lm93_data *data;
+	struct i2c_client *client;
+
+	int err = -ENODEV, func;
+	void (*update)(struct lm93_data *, struct i2c_client *);
+
+	/* choose update routine based on bus capabilities */
+	func = i2c_get_functionality(adapter);
+	if ( ((LM93_SMBUS_FUNC_FULL & func) == LM93_SMBUS_FUNC_FULL) &&
+			(!disable_block) ) {
+		dev_dbg(&adapter->dev,"using SMBus block data transactions\n");
+		update = lm93_update_client_full;
+	} else if ((LM93_SMBUS_FUNC_MIN & func) == LM93_SMBUS_FUNC_MIN) {
+		dev_dbg(&adapter->dev,"disabled SMBus block data "
+			"transactions\n");
+		update = lm93_update_client_min;
+	} else {
+		dev_dbg(&adapter->dev,"detect failed, "
+			"smbus byte and/or word data not supported!\n");
+		goto err_out;
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access lm78_{read,write}_value. */
+
+	if ( !(data = kzalloc(sizeof(struct lm93_data), GFP_KERNEL))) {
+		dev_dbg(&adapter->dev,"out of memory!\n");
+		err = -ENOMEM;
+		goto err_out;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &lm93_driver;
+
+	/* detection */
+	if (kind < 0) {
+		int mfr = lm93_read_byte(client, LM93_REG_MFR_ID);
+
+		if (mfr != 0x01) {
+			dev_dbg(&adapter->dev,"detect failed, "
+				"bad manufacturer id 0x%02x!\n", mfr);
+			goto err_free;
+		}
+	}
+
+	if (kind <= 0) {
+		int ver = lm93_read_byte(client, LM93_REG_VER);
+
+		if ((ver == LM93_MFR_ID) || (ver == LM93_MFR_ID_PROTOTYPE)) {
+			kind = lm93;
+		} else {
+			dev_dbg(&adapter->dev,"detect failed, "
+				"bad version id 0x%02x!\n", ver);
+			if (kind == 0)
+				dev_dbg(&adapter->dev,
+					"(ignored 'force' parameter)\n");
+			goto err_free;
+		}
+	}
+
+	/* fill in remaining client fields */
+	strlcpy(client->name, "lm93", I2C_NAME_SIZE);
+	dev_dbg(&adapter->dev,"loading %s at %d,0x%02x\n",
+		client->name, i2c_adapter_id(client->adapter),
+		client->addr);
+
+	/* housekeeping */
+	data->valid = 0;
+	data->update = update;
+	mutex_init(&data->update_lock);
+
+	/* tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto err_free;
+
+	/* initialize the chip */
+	lm93_init_client(client);
+
+	err = sysfs_create_group(&client->dev.kobj, &lm93_attr_grp);
+	if (err)
+		goto err_detach;
+
+	/* Register hwmon driver class */
+	data->class_dev = hwmon_device_register(&client->dev);
+	if ( !IS_ERR(data->class_dev))
+		return 0;
+
+	err = PTR_ERR(data->class_dev);
+	dev_err(&client->dev, "error registering hwmon device.\n");
+	sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
+err_detach:
+	i2c_detach_client(client);
+err_free:
+	kfree(data);
+err_out:
+	return err;
+}
+
+/* This function is called when:
+     * lm93_driver is inserted (when this module is loaded), for each
+       available adapter
+     * when a new adapter is inserted (and lm93_driver is still present) */
+static int lm93_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_probe(adapter, &addr_data, lm93_detect);
+}
+
+static int lm93_detach_client(struct i2c_client *client)
+{
+	struct lm93_data *data = i2c_get_clientdata(client);
+	int err = 0;
+
+	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &lm93_attr_grp);
+
+	err = i2c_detach_client(client);
+	if (!err)
+		kfree(data);
+	return err;
+}
+
+static struct i2c_driver lm93_driver = {
+	.driver = {
+		.name	= "lm93",
+	},
+	.attach_adapter	= lm93_attach_adapter,
+	.detach_client	= lm93_detach_client,
+};
+
+static int __init lm93_init(void)
+{
+	return i2c_add_driver(&lm93_driver);
+}
+
+static void __exit lm93_exit(void)
+{
+	i2c_del_driver(&lm93_driver);
+}
+
+MODULE_AUTHOR("Mark M. Hoffman <mhoffman@lightlink.com>, "
+		"Hans J. Koch <hjk@linutronix.de");
+MODULE_DESCRIPTION("LM93 driver");
+MODULE_LICENSE("GPL");
+
+module_init(lm93_init);
+module_exit(lm93_exit);
diff --git a/drivers/hwmon/pc87360.c b/drivers/hwmon/pc87360.c
index c8a21be09d87..f57c75d59a5b 100644
--- a/drivers/hwmon/pc87360.c
+++ b/drivers/hwmon/pc87360.c
@@ -1,7 +1,7 @@
 /*
  *  pc87360.c - Part of lm_sensors, Linux kernel modules
  *              for hardware monitoring
- *  Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
+ *  Copyright (C) 2004, 2007 Jean Delvare <khali@linux-fr.org>
  *
  *  Copied from smsc47m1.c:
  *  Copyright (C) 2002 Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -37,8 +37,7 @@
 #include <linux/init.h>
 #include <linux/slab.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
@@ -47,12 +46,10 @@
 #include <asm/io.h>
 
 static u8 devid;
-static unsigned short address;
+static struct platform_device *pdev;
 static unsigned short extra_isa[3];
 static u8 confreg[4];
 
-enum chips { any_chip, pc87360, pc87363, pc87364, pc87365, pc87366 };
-
 static int init = 1;
 module_param(init, int, 0);
 MODULE_PARM_DESC(init,
@@ -178,11 +175,11 @@ static inline u8 PWM_TO_REG(int val, int inv)
 					 ((val) + 500) / 1000)
 
 /*
- * Client data (each client gets its own)
+ * Device data
  */
 
 struct pc87360_data {
-	struct i2c_client client;
+	const char *name;
 	struct class_device *class_dev;
 	struct mutex lock;
 	struct mutex update_lock;
@@ -222,27 +219,28 @@ struct pc87360_data {
  * Functions declaration
  */
 
-static int pc87360_detect(struct i2c_adapter *adapter);
-static int pc87360_detach_client(struct i2c_client *client);
+static int pc87360_probe(struct platform_device *pdev);
+static int __devexit pc87360_remove(struct platform_device *pdev);
 
 static int pc87360_read_value(struct pc87360_data *data, u8 ldi, u8 bank,
 			      u8 reg);
 static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
 				u8 reg, u8 value);
-static void pc87360_init_client(struct i2c_client *client, int use_thermistors);
+static void pc87360_init_device(struct platform_device *pdev,
+				int use_thermistors);
 static struct pc87360_data *pc87360_update_device(struct device *dev);
 
 /*
- * Driver data (common to all clients)
+ * Driver data
  */
 
-static struct i2c_driver pc87360_driver = {
+static struct platform_driver pc87360_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "pc87360",
 	},
-	.attach_adapter	= pc87360_detect,
-	.detach_client	= pc87360_detach_client,
+	.probe		= pc87360_probe,
+	.remove		= __devexit_p(pc87360_remove),
 };
 
 /*
@@ -281,8 +279,7 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *devattr,
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long fan_min = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -347,8 +344,7 @@ static ssize_t set_pwm(struct device *dev, struct device_attribute *devattr, con
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -410,8 +406,7 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *devattr,
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -425,8 +420,7 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *devattr,
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -511,8 +505,7 @@ static ssize_t show_vrm(struct device *dev, struct device_attribute *attr, char
 }
 static ssize_t set_vrm(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	data->vrm = simple_strtoul(buf, NULL, 10);
 	return count;
 }
@@ -584,8 +577,7 @@ static ssize_t set_therm_min(struct device *dev, struct device_attribute *devatt
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -599,8 +591,7 @@ static ssize_t set_therm_max(struct device *dev, struct device_attribute *devatt
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -614,8 +605,7 @@ static ssize_t set_therm_crit(struct device *dev, struct device_attribute *devat
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -715,8 +705,7 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *devattr
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -730,8 +719,7 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *devattr
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -745,8 +733,7 @@ static ssize_t set_temp_crit(struct device *dev, struct device_attribute *devatt
 	size_t count)
 {
 	struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
@@ -818,6 +805,14 @@ static const struct attribute_group pc8736x_temp_group = {
 	.attrs = pc8736x_temp_attr_array,
 };
 
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct pc87360_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 /*
  * Device detection, registration and update
  */
@@ -912,28 +907,18 @@ static int __init pc87360_find(int sioaddr, u8 *devid, unsigned short *addresses
 	return 0;
 }
 
-static int pc87360_detect(struct i2c_adapter *adapter)
+static int __devinit pc87360_probe(struct platform_device *pdev)
 {
 	int i;
-	struct i2c_client *client;
 	struct pc87360_data *data;
 	int err = 0;
 	const char *name = "pc87360";
 	int use_thermistors = 0;
-	struct device *dev;
+	struct device *dev = &pdev->dev;
 
 	if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
 		return -ENOMEM;
 
-	client = &data->client;
-	dev = &client->dev;
-	i2c_set_clientdata(client, data);
-	client->addr = address;
-	mutex_init(&data->lock);
-	client->adapter = adapter;
-	client->driver = &pc87360_driver;
-	client->flags = 0;
-
 	data->fannr = 2;
 	data->innr = 0;
 	data->tempnr = 0;
@@ -960,15 +945,17 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 		break;
 	}
 
-	strlcpy(client->name, name, sizeof(client->name));
+	data->name = name;
 	data->valid = 0;
+	mutex_init(&data->lock);
 	mutex_init(&data->update_lock);
+	platform_set_drvdata(pdev, data);
 
 	for (i = 0; i < 3; i++) {
 		if (((data->address[i] = extra_isa[i]))
 		 && !request_region(extra_isa[i], PC87360_EXTENT,
 		 		    pc87360_driver.driver.name)) {
-			dev_err(&client->dev, "Region 0x%x-0x%x already "
+			dev_err(dev, "Region 0x%x-0x%x already "
 				"in use!\n", extra_isa[i],
 				extra_isa[i]+PC87360_EXTENT-1);
 			for (i--; i >= 0; i--)
@@ -982,9 +969,6 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 	if (data->fannr)
 		data->fan_conf = confreg[0] | (confreg[1] << 8);
 
-	if ((err = i2c_attach_client(client)))
-		goto ERROR2;
-
 	/* Use the correct reference voltage
 	   Unless both the VLM and the TMS logical devices agree to
 	   use an external Vref, the internal one is used. */
@@ -996,7 +980,7 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 						PC87365_REG_TEMP_CONFIG);
 		}
 		data->in_vref = (i&0x02) ? 3025 : 2966;
-		dev_dbg(&client->dev, "Using %s reference voltage\n",
+		dev_dbg(dev, "Using %s reference voltage\n",
 			(i&0x02) ? "external" : "internal");
 
 		data->vid_conf = confreg[3];
@@ -1015,18 +999,18 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 		if (devid == 0xe9 && data->address[1]) /* PC87366 */
 			use_thermistors = confreg[2] & 0x40;
 
-		pc87360_init_client(client, use_thermistors);
+		pc87360_init_device(pdev, use_thermistors);
 	}
 
 	/* Register all-or-nothing sysfs groups */
 
 	if (data->innr &&
-	    (err = sysfs_create_group(&client->dev.kobj,
+	    (err = sysfs_create_group(&dev->kobj,
 				      &pc8736x_vin_group)))
 		goto ERROR3;
 
 	if (data->innr == 14 &&
-	    (err = sysfs_create_group(&client->dev.kobj,
+	    (err = sysfs_create_group(&dev->kobj,
 				      &pc8736x_therm_group)))
 		goto ERROR3;
 
@@ -1067,7 +1051,10 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 			goto ERROR3;
 	}
 
-	data->class_dev = hwmon_device_register(&client->dev);
+	if ((err = device_create_file(dev, &dev_attr_name)))
+		goto ERROR3;
+
+	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto ERROR3;
@@ -1075,14 +1062,12 @@ static int pc87360_detect(struct i2c_adapter *adapter)
 	return 0;
 
 ERROR3:
+	device_remove_file(dev, &dev_attr_name);
 	/* can still remove groups whose members were added individually */
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
-
-	i2c_detach_client(client);
-ERROR2:
+	sysfs_remove_group(&dev->kobj, &pc8736x_temp_group);
+	sysfs_remove_group(&dev->kobj, &pc8736x_fan_group);
+	sysfs_remove_group(&dev->kobj, &pc8736x_therm_group);
+	sysfs_remove_group(&dev->kobj, &pc8736x_vin_group);
 	for (i = 0; i < 3; i++) {
 		if (data->address[i]) {
 			release_region(data->address[i], PC87360_EXTENT);
@@ -1093,20 +1078,18 @@ ERROR1:
 	return err;
 }
 
-static int pc87360_detach_client(struct i2c_client *client)
+static int __devexit pc87360_remove(struct platform_device *pdev)
 {
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = platform_get_drvdata(pdev);
 	int i;
 
 	hwmon_device_unregister(data->class_dev);
 
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_temp_group);
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_fan_group);
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_therm_group);
-	sysfs_remove_group(&client->dev.kobj, &pc8736x_vin_group);
-
-	if ((i = i2c_detach_client(client)))
-		return i;
+	device_remove_file(&pdev->dev, &dev_attr_name);
+	sysfs_remove_group(&pdev->dev.kobj, &pc8736x_temp_group);
+	sysfs_remove_group(&pdev->dev.kobj, &pc8736x_fan_group);
+	sysfs_remove_group(&pdev->dev.kobj, &pc8736x_therm_group);
+	sysfs_remove_group(&pdev->dev.kobj, &pc8736x_vin_group);
 
 	for (i = 0; i < 3; i++) {
 		if (data->address[i]) {
@@ -1144,9 +1127,10 @@ static void pc87360_write_value(struct pc87360_data *data, u8 ldi, u8 bank,
 	mutex_unlock(&(data->lock));
 }
 
-static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
+static void pc87360_init_device(struct platform_device *pdev,
+				int use_thermistors)
 {
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = platform_get_drvdata(pdev);
 	int i, nr;
 	const u8 init_in[14] = { 2, 2, 2, 2, 2, 2, 2, 1, 1, 3, 1, 2, 2, 2 };
 	const u8 init_temp[3] = { 2, 2, 1 };
@@ -1155,7 +1139,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 	if (init >= 2 && data->innr) {
 		reg = pc87360_read_value(data, LD_IN, NO_BANK,
 					 PC87365_REG_IN_CONVRATE);
-		dev_info(&client->dev, "VLM conversion set to "
+		dev_info(&pdev->dev, "VLM conversion set to "
 			 "1s period, 160us delay\n");
 		pc87360_write_value(data, LD_IN, NO_BANK,
 				    PC87365_REG_IN_CONVRATE,
@@ -1169,7 +1153,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 			reg = pc87360_read_value(data, LD_IN, i,
 						 PC87365_REG_IN_STATUS);
 			if (!(reg & 0x01)) {
-				dev_dbg(&client->dev, "Forcibly "
+				dev_dbg(&pdev->dev, "Forcibly "
 					"enabling in%d\n", i);
 				pc87360_write_value(data, LD_IN, i,
 						    PC87365_REG_IN_STATUS,
@@ -1193,7 +1177,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 			reg = pc87360_read_value(data, LD_TEMP, i,
 						 PC87365_REG_TEMP_STATUS);
 			if (!(reg & 0x01)) {
-				dev_dbg(&client->dev, "Forcibly "
+				dev_dbg(&pdev->dev, "Forcibly "
 					"enabling temp%d\n", i+1);
 				pc87360_write_value(data, LD_TEMP, i,
 						    PC87365_REG_TEMP_STATUS,
@@ -1210,7 +1194,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 				reg = pc87360_read_value(data, LD_TEMP,
 				      (i-11)/2, PC87365_REG_TEMP_STATUS);
 				if (reg & 0x01) {
-					dev_dbg(&client->dev, "Skipping "
+					dev_dbg(&pdev->dev, "Skipping "
 						"temp%d, pin already in use "
 						"by temp%d\n", i-7, (i-11)/2);
 					continue;
@@ -1220,7 +1204,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 				reg = pc87360_read_value(data, LD_IN, i,
 							 PC87365_REG_IN_STATUS);
 				if (!(reg & 0x01)) {
-					dev_dbg(&client->dev, "Forcibly "
+					dev_dbg(&pdev->dev, "Forcibly "
 						"enabling temp%d\n", i-7);
 					pc87360_write_value(data, LD_IN, i,
 						PC87365_REG_TEMP_STATUS,
@@ -1234,7 +1218,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 		reg = pc87360_read_value(data, LD_IN, NO_BANK,
 					 PC87365_REG_IN_CONFIG);
 		if (reg & 0x01) {
-			dev_dbg(&client->dev, "Forcibly "
+			dev_dbg(&pdev->dev, "Forcibly "
 				"enabling monitoring (VLM)\n");
 			pc87360_write_value(data, LD_IN, NO_BANK,
 					    PC87365_REG_IN_CONFIG,
@@ -1246,7 +1230,7 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 		reg = pc87360_read_value(data, LD_TEMP, NO_BANK,
 					 PC87365_REG_TEMP_CONFIG);
 		if (reg & 0x01) {
-			dev_dbg(&client->dev, "Forcibly enabling "
+			dev_dbg(&pdev->dev, "Forcibly enabling "
 				"monitoring (TMS)\n");
 			pc87360_write_value(data, LD_TEMP, NO_BANK,
 					    PC87365_REG_TEMP_CONFIG,
@@ -1268,9 +1252,9 @@ static void pc87360_init_client(struct i2c_client *client, int use_thermistors)
 	}
 }
 
-static void pc87360_autodiv(struct i2c_client *client, int nr)
+static void pc87360_autodiv(struct device *dev, int nr)
 {
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	u8 old_min = data->fan_min[nr];
 
 	/* Increase clock divider if needed and possible */
@@ -1280,7 +1264,7 @@ static void pc87360_autodiv(struct i2c_client *client, int nr)
 			data->fan_status[nr] += 0x20;
 			data->fan_min[nr] >>= 1;
 			data->fan[nr] >>= 1;
-			dev_dbg(&client->dev, "Increasing "
+			dev_dbg(dev, "Increasing "
 				"clock divider to %d for fan %d\n",
 				FAN_DIV_FROM_REG(data->fan_status[nr]), nr+1);
 		}
@@ -1292,7 +1276,7 @@ static void pc87360_autodiv(struct i2c_client *client, int nr)
 			data->fan_status[nr] -= 0x20;
 			data->fan_min[nr] <<= 1;
 			data->fan[nr] <<= 1;
-			dev_dbg(&client->dev, "Decreasing "
+			dev_dbg(dev, "Decreasing "
 				"clock divider to %d for fan %d\n",
 				FAN_DIV_FROM_REG(data->fan_status[nr]),
 				nr+1);
@@ -1309,14 +1293,13 @@ static void pc87360_autodiv(struct i2c_client *client, int nr)
 
 static struct pc87360_data *pc87360_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct pc87360_data *data = i2c_get_clientdata(client);
+	struct pc87360_data *data = dev_get_drvdata(dev);
 	u8 i;
 
 	mutex_lock(&data->update_lock);
 
 	if (time_after(jiffies, data->last_updated + HZ * 2) || !data->valid) {
-		dev_dbg(&client->dev, "Data update\n");
+		dev_dbg(dev, "Data update\n");
 
 		/* Fans */
 		for (i = 0; i < data->fannr; i++) {
@@ -1330,7 +1313,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
 						   LD_FAN, NO_BANK,
 						   PC87360_REG_FAN_MIN(i));
 				/* Change clock divider if needed */
-				pc87360_autodiv(client, i);
+				pc87360_autodiv(dev, i);
 				/* Clear bits and write new divider */
 				pc87360_write_value(data, LD_FAN, NO_BANK,
 						    PC87360_REG_FAN_STATUS(i),
@@ -1418,9 +1401,53 @@ static struct pc87360_data *pc87360_update_device(struct device *dev)
 	return data;
 }
 
+static int __init pc87360_device_add(unsigned short address)
+{
+	struct resource res = {
+		.name	= "pc87360",
+		.flags	= IORESOURCE_IO,
+	};
+	int err, i;
+
+	pdev = platform_device_alloc("pc87360", address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR "pc87360: Device allocation failed\n");
+		goto exit;
+	}
+
+	for (i = 0; i < 3; i++) {
+		if (!extra_isa[i])
+			continue;
+		res.start = extra_isa[i];
+		res.end = extra_isa[i] + PC87360_EXTENT - 1;
+		err = platform_device_add_resources(pdev, &res, 1);
+		if (err) {
+			printk(KERN_ERR "pc87360: Device resource[%d] "
+			       "addition failed (%d)\n", i, err);
+			goto exit_device_put;
+		}
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR "pc87360: 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 pc87360_init(void)
 {
-	int i;
+	int err, i;
+	unsigned short address = 0;
 
 	if (pc87360_find(0x2e, &devid, extra_isa)
 	 && pc87360_find(0x4e, &devid, extra_isa)) {
@@ -1443,12 +1470,27 @@ static int __init pc87360_init(void)
 		return -ENODEV;
 	}
 
-	return i2c_isa_add_driver(&pc87360_driver);
+	err = platform_driver_register(&pc87360_driver);
+	if (err)
+		goto exit;
+
+	/* Sets global pdev as a side effect */
+	err = pc87360_device_add(address);
+	if (err)
+		goto exit_driver;
+
+	return 0;
+
+ exit_driver:
+	platform_driver_unregister(&pc87360_driver);
+ exit:
+	return err;
 }
 
 static void __exit pc87360_exit(void)
 {
-	i2c_isa_del_driver(&pc87360_driver);
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&pc87360_driver);
 }
 
 
diff --git a/drivers/hwmon/pc87427.c b/drivers/hwmon/pc87427.c
index 29354fa26f81..2915bc4ad0d5 100644
--- a/drivers/hwmon/pc87427.c
+++ b/drivers/hwmon/pc87427.c
@@ -484,7 +484,6 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
 	struct resource *res;
 	int i;
 
-	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
 	device_remove_file(&pdev->dev, &dev_attr_name);
 	for (i = 0; i < 8; i++) {
@@ -492,6 +491,7 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
 			continue;
 		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
 	}
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
diff --git a/drivers/hwmon/sis5595.c b/drivers/hwmon/sis5595.c
index 3f400263fc0f..92956eb3f3c1 100644
--- a/drivers/hwmon/sis5595.c
+++ b/drivers/hwmon/sis5595.c
@@ -54,9 +54,9 @@
 #include <linux/slab.h>
 #include <linux/ioport.h>
 #include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/jiffies.h>
@@ -72,17 +72,13 @@ module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
 
-/* Device address
-   Note that we can't determine the ISA address until we have initialized
-   our module */
-static unsigned short address;
+static struct platform_device *pdev;
 
 /* Many SIS5595 constants specified below */
 
 /* Length of ISA address segment */
 #define SIS5595_EXTENT 8
 /* PCI Config Registers */
-#define SIS5595_REVISION_REG 0x08
 #define SIS5595_BASE_REG 0x68
 #define SIS5595_PIN_REG 0x7A
 #define SIS5595_ENABLE_REG 0x7B
@@ -165,7 +161,8 @@ static inline u8 DIV_TO_REG(int val)
 /* For each registered chip, we need to keep some data in memory.
    The structure is dynamically allocated. */
 struct sis5595_data {
-	struct i2c_client client;
+	unsigned short addr;
+	const char *name;
 	struct class_device *class_dev;
 	struct mutex lock;
 
@@ -189,102 +186,88 @@ struct sis5595_data {
 
 static struct pci_dev *s_bridge;	/* pointer to the (only) sis5595 */
 
-static int sis5595_detect(struct i2c_adapter *adapter);
-static int sis5595_detach_client(struct i2c_client *client);
+static int sis5595_probe(struct platform_device *pdev);
+static int __devexit sis5595_remove(struct platform_device *pdev);
 
-static int sis5595_read_value(struct i2c_client *client, u8 reg);
-static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value);
+static int sis5595_read_value(struct sis5595_data *data, u8 reg);
+static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value);
 static struct sis5595_data *sis5595_update_device(struct device *dev);
-static void sis5595_init_client(struct i2c_client *client);
+static void sis5595_init_device(struct sis5595_data *data);
 
-static struct i2c_driver sis5595_driver = {
+static struct platform_driver sis5595_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "sis5595",
 	},
-	.attach_adapter	= sis5595_detect,
-	.detach_client	= sis5595_detach_client,
+	.probe		= sis5595_probe,
+	.remove		= __devexit_p(sis5595_remove),
 };
 
 /* 4 Voltages */
-static ssize_t show_in(struct device *dev, char *buf, int nr)
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+		       char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in[nr]));
 }
 
-static ssize_t show_in_min(struct device *dev, char *buf, int nr)
+static ssize_t show_in_min(struct device *dev, struct device_attribute *da,
+			   char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_min[nr]));
 }
 
-static ssize_t show_in_max(struct device *dev, char *buf, int nr)
+static ssize_t show_in_max(struct device *dev, struct device_attribute *da,
+			   char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", IN_FROM_REG(data->in_max[nr]));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf,
-	       size_t count, int nr)
+static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
+			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val);
-	sis5595_write_value(client, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
+	sis5595_write_value(data, SIS5595_REG_IN_MIN(nr), data->in_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t set_in_max(struct device *dev, const char *buf,
-	       size_t count, int nr)
+static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
+			  const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val);
-	sis5595_write_value(client, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
+	sis5595_write_value(data, SIS5595_REG_IN_MAX(nr), data->in_max[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
 #define show_in_offset(offset)					\
-static ssize_t							\
-	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
-{								\
-	return show_in(dev, buf, offset);			\
-}								\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, 		\
-		show_in##offset, NULL);				\
-static ssize_t							\
-	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
-{								\
-	return show_in_min(dev, buf, offset);			\
-}								\
-static ssize_t							\
-	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
-{								\
-	return show_in_max(dev, buf, offset);			\
-}								\
-static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr,	\
-		const char *buf, size_t count)			\
-{								\
-	return set_in_min(dev, buf, count, offset);		\
-}								\
-static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,	\
-		const char *buf, size_t count)			\
-{								\
-	return set_in_max(dev, buf, count, offset);		\
-}								\
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,		\
-		show_in##offset##_min, set_in##offset##_min);	\
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,		\
-		show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
+		show_in, NULL, offset);				\
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_in_min, set_in_min, offset);		\
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_in_max, set_in_max, offset);
 
 show_in_offset(0);
 show_in_offset(1);
@@ -307,13 +290,12 @@ static ssize_t show_temp_over(struct device *dev, struct device_attribute *attr,
 
 static ssize_t set_temp_over(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_over = TEMP_TO_REG(val);
-	sis5595_write_value(client, SIS5595_REG_TEMP_OVER, data->temp_over);
+	sis5595_write_value(data, SIS5595_REG_TEMP_OVER, data->temp_over);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -326,13 +308,12 @@ static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *attr,
 
 static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
 	long val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst = TEMP_TO_REG(val);
-	sis5595_write_value(client, SIS5595_REG_TEMP_HYST, data->temp_hyst);
+	sis5595_write_value(data, SIS5595_REG_TEMP_HYST, data->temp_hyst);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -344,37 +325,47 @@ static DEVICE_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
 		show_temp_hyst, set_temp_hyst);
 
 /* 2 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr)
+static ssize_t show_fan(struct device *dev, struct device_attribute *da,
+			char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 		DIV_FROM_REG(data->fan_div[nr])) );
 }
 
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
+			    char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf,"%d\n", FAN_FROM_REG(data->fan_min[nr],
 		DIV_FROM_REG(data->fan_div[nr])) );
 }
 
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-		size_t count, int nr)
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-	sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
+	sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
+			    char *buf)
 {
 	struct sis5595_data *data = sis5595_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
 }
 
@@ -382,11 +373,12 @@ static ssize_t show_fan_div(struct device *dev, char *buf, int nr)
    determined in part by the fan divisor.  This follows the principle of
    least surprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-	size_t count, int nr)
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
+			   const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	unsigned long min;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int reg;
@@ -394,7 +386,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
 	mutex_lock(&data->update_lock);
 	min = FAN_FROM_REG(data->fan_min[nr],
 			DIV_FROM_REG(data->fan_div[nr]));
-	reg = sis5595_read_value(client, SIS5595_REG_FANDIV);
+	reg = sis5595_read_value(data, SIS5595_REG_FANDIV);
 
 	switch (val) {
 	case 1: data->fan_div[nr] = 0; break;
@@ -402,7 +394,7 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
 	case 4: data->fan_div[nr] = 2; break;
 	case 8: data->fan_div[nr] = 3; break;
 	default:
-		dev_err(&client->dev, "fan_div value %ld not "
+		dev_err(dev, "fan_div value %ld not "
 			"supported. Choose one of 1, 2, 4 or 8!\n", val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
@@ -416,55 +408,25 @@ static ssize_t set_fan_div(struct device *dev, const char *buf,
 		reg = (reg & 0x3f) | (data->fan_div[nr] << 6);
 		break;
 	}
-	sis5595_write_value(client, SIS5595_REG_FANDIV, reg);
+	sis5595_write_value(data, SIS5595_REG_FANDIV, reg);
 	data->fan_min[nr] =
 		FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-	sis5595_write_value(client, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
+	sis5595_write_value(data, SIS5595_REG_FAN_MIN(nr), data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
 #define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan_min(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan_div(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr,		\
-		const char *buf, size_t count)				\
-{									\
-	return set_fan_min(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
-		show_fan_##offset##_min, set_fan_##offset##_min);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
+		show_fan, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
+		show_fan_min, set_fan_min, offset - 1);			\
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
+		show_fan_div, set_fan_div, offset - 1);
 
 show_fan_offset(1);
 show_fan_offset(2);
 
-static ssize_t set_fan_1_div(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
-{
-	return set_fan_div(dev, buf, count, 0) ;
-}
-
-static ssize_t set_fan_2_div(struct device *dev, struct device_attribute *attr, const char *buf,
-		size_t count)
-{
-	return set_fan_div(dev, buf, count, 1) ;
-}
-static DEVICE_ATTR(fan1_div, S_IRUGO | S_IWUSR,
-		show_fan_1_div, set_fan_1_div);
-static DEVICE_ATTR(fan2_div, S_IRUGO | S_IWUSR,
-		show_fan_2_div, set_fan_2_div);
-
 /* Alarms */
 static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, char *buf)
 {
@@ -473,28 +435,37 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct sis5595_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 static struct attribute *sis5595_attributes[] = {
-	&dev_attr_in0_input.attr,
-	&dev_attr_in0_min.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in1_min.attr,
-	&dev_attr_in1_max.attr,
-	&dev_attr_in2_input.attr,
-	&dev_attr_in2_min.attr,
-	&dev_attr_in2_max.attr,
-	&dev_attr_in3_input.attr,
-	&dev_attr_in3_min.attr,
-	&dev_attr_in3_max.attr,
-
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_fan1_div.attr,
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_fan2_div.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
+	&dev_attr_name.attr,
 	NULL
 };
 
@@ -503,9 +474,9 @@ static const struct attribute_group sis5595_group = {
 };
 
 static struct attribute *sis5595_attributes_opt[] = {
-	&dev_attr_in4_input.attr,
-	&dev_attr_in4_min.attr,
-	&dev_attr_in4_max.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
 
 	&dev_attr_temp1_input.attr,
 	&dev_attr_temp1_max.attr,
@@ -518,68 +489,35 @@ static const struct attribute_group sis5595_group_opt = {
 };
  
 /* This is called when the module is loaded */
-static int sis5595_detect(struct i2c_adapter *adapter)
+static int __devinit sis5595_probe(struct platform_device *pdev)
 {
 	int err = 0;
 	int i;
-	struct i2c_client *new_client;
 	struct sis5595_data *data;
+	struct resource *res;
 	char val;
-	u16 a;
 
-	if (force_addr)
-		address = force_addr & ~(SIS5595_EXTENT - 1);
 	/* Reserve the ISA region */
-	if (!request_region(address, SIS5595_EXTENT,
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start, SIS5595_EXTENT,
 			    sis5595_driver.driver.name)) {
 		err = -EBUSY;
 		goto exit;
 	}
-	if (force_addr) {
-		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n", address);
-		if (PCIBIOS_SUCCESSFUL !=
-		    pci_write_config_word(s_bridge, SIS5595_BASE_REG, address))
-			goto exit_release;
-		if (PCIBIOS_SUCCESSFUL !=
-		    pci_read_config_word(s_bridge, SIS5595_BASE_REG, &a))
-			goto exit_release;
-		if ((a & ~(SIS5595_EXTENT - 1)) != address)
-			/* doesn't work for some chips? */
-			goto exit_release;
-	}
-
-	if (PCIBIOS_SUCCESSFUL !=
-	    pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val)) {
-		goto exit_release;
-	}
-	if ((val & 0x80) == 0) {
-		if (PCIBIOS_SUCCESSFUL !=
-		    pci_write_config_byte(s_bridge, SIS5595_ENABLE_REG,
-					  val | 0x80))
-			goto exit_release;
-		if (PCIBIOS_SUCCESSFUL !=
-		    pci_read_config_byte(s_bridge, SIS5595_ENABLE_REG, &val))
-			goto exit_release;
-		if ((val & 0x80) == 0) 
-			/* doesn't work for some chips! */
-			goto exit_release;
-	}
 
 	if (!(data = kzalloc(sizeof(struct sis5595_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit_release;
 	}
 
-	new_client = &data->client;
-	new_client->addr = address;
 	mutex_init(&data->lock);
-	i2c_set_clientdata(new_client, data);
-	new_client->adapter = adapter;
-	new_client->driver = &sis5595_driver;
-	new_client->flags = 0;
+	mutex_init(&data->update_lock);
+	data->addr = res->start;
+	data->name = "sis5595";
+	platform_set_drvdata(pdev, data);
 
 	/* Check revision and pin registers to determine whether 4 or 5 voltages */
-	pci_read_config_byte(s_bridge, SIS5595_REVISION_REG, &(data->revision));
+	pci_read_config_byte(s_bridge, PCI_REVISION_ID, &data->revision);
 	/* 4 voltages, 1 temp */
 	data->maxins = 3;
 	if (data->revision >= REV2MIN) {
@@ -589,47 +527,37 @@ static int sis5595_detect(struct i2c_adapter *adapter)
 			data->maxins = 4;
 	}
 	
-	/* Fill in the remaining client fields and put it into the global list */
-	strlcpy(new_client->name, "sis5595", I2C_NAME_SIZE);
-
-	data->valid = 0;
-	mutex_init(&data->update_lock);
-
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
-		goto exit_free;
-	
 	/* Initialize the SIS5595 chip */
-	sis5595_init_client(new_client);
+	sis5595_init_device(data);
 
 	/* A few vars need to be filled upon startup */
 	for (i = 0; i < 2; i++) {
-		data->fan_min[i] = sis5595_read_value(new_client,
+		data->fan_min[i] = sis5595_read_value(data,
 					SIS5595_REG_FAN_MIN(i));
 	}
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &sis5595_group)))
-		goto exit_detach;
+	if ((err = sysfs_create_group(&pdev->dev.kobj, &sis5595_group)))
+		goto exit_free;
 	if (data->maxins == 4) {
-		if ((err = device_create_file(&new_client->dev,
-					      &dev_attr_in4_input))
-		 || (err = device_create_file(&new_client->dev,
-					      &dev_attr_in4_min))
-		 || (err = device_create_file(&new_client->dev,
-					      &dev_attr_in4_max)))
+		if ((err = device_create_file(&pdev->dev,
+					&sensor_dev_attr_in4_input.dev_attr))
+		 || (err = device_create_file(&pdev->dev,
+					&sensor_dev_attr_in4_min.dev_attr))
+		 || (err = device_create_file(&pdev->dev,
+					&sensor_dev_attr_in4_max.dev_attr)))
 			goto exit_remove_files;
 	} else {
-		if ((err = device_create_file(&new_client->dev,
+		if ((err = device_create_file(&pdev->dev,
 					      &dev_attr_temp1_input))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(&pdev->dev,
 					      &dev_attr_temp1_max))
-		 || (err = device_create_file(&new_client->dev,
+		 || (err = device_create_file(&pdev->dev,
 					      &dev_attr_temp1_max_hyst)))
 			goto exit_remove_files;
 	}
 
-	data->class_dev = hwmon_device_register(&new_client->dev);
+	data->class_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto exit_remove_files;
@@ -638,32 +566,26 @@ static int sis5595_detect(struct i2c_adapter *adapter)
 	return 0;
 
 exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &sis5595_group);
-	sysfs_remove_group(&new_client->dev.kobj, &sis5595_group_opt);
-exit_detach:
-	i2c_detach_client(new_client);
+	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
+	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
 exit_free:
 	kfree(data);
 exit_release:
-	release_region(address, SIS5595_EXTENT);
+	release_region(res->start, SIS5595_EXTENT);
 exit:
 	return err;
 }
 
-static int sis5595_detach_client(struct i2c_client *client)
+static int __devexit sis5595_remove(struct platform_device *pdev)
 {
-	struct sis5595_data *data = i2c_get_clientdata(client);
-	int err;
+	struct sis5595_data *data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(data->class_dev);
-	sysfs_remove_group(&client->dev.kobj, &sis5595_group);
-	sysfs_remove_group(&client->dev.kobj, &sis5595_group_opt);
-
-	if ((err = i2c_detach_client(client)))
-		return err;
-
-	release_region(client->addr, SIS5595_EXTENT);
+	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group);
+	sysfs_remove_group(&pdev->dev.kobj, &sis5595_group_opt);
 
+	release_region(data->addr, SIS5595_EXTENT);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
@@ -671,41 +593,37 @@ static int sis5595_detach_client(struct i2c_client *client)
 
 
 /* ISA access must be locked explicitly. */
-static int sis5595_read_value(struct i2c_client *client, u8 reg)
+static int sis5595_read_value(struct sis5595_data *data, u8 reg)
 {
 	int res;
 
-	struct sis5595_data *data = i2c_get_clientdata(client);
 	mutex_lock(&data->lock);
-	outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
-	res = inb_p(client->addr + SIS5595_DATA_REG_OFFSET);
+	outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET);
+	res = inb_p(data->addr + SIS5595_DATA_REG_OFFSET);
 	mutex_unlock(&data->lock);
 	return res;
 }
 
-static int sis5595_write_value(struct i2c_client *client, u8 reg, u8 value)
+static void sis5595_write_value(struct sis5595_data *data, u8 reg, u8 value)
 {
-	struct sis5595_data *data = i2c_get_clientdata(client);
 	mutex_lock(&data->lock);
-	outb_p(reg, client->addr + SIS5595_ADDR_REG_OFFSET);
-	outb_p(value, client->addr + SIS5595_DATA_REG_OFFSET);
+	outb_p(reg, data->addr + SIS5595_ADDR_REG_OFFSET);
+	outb_p(value, data->addr + SIS5595_DATA_REG_OFFSET);
 	mutex_unlock(&data->lock);
-	return 0;
 }
 
 /* Called when we have found a new SIS5595. */
-static void sis5595_init_client(struct i2c_client *client)
+static void __devinit sis5595_init_device(struct sis5595_data *data)
 {
-	u8 config = sis5595_read_value(client, SIS5595_REG_CONFIG);
+	u8 config = sis5595_read_value(data, SIS5595_REG_CONFIG);
 	if (!(config & 0x01))
-		sis5595_write_value(client, SIS5595_REG_CONFIG,
+		sis5595_write_value(data, SIS5595_REG_CONFIG,
 				(config & 0xf7) | 0x01);
 }
 
 static struct sis5595_data *sis5595_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct sis5595_data *data = i2c_get_clientdata(client);
+	struct sis5595_data *data = dev_get_drvdata(dev);
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -715,35 +633,35 @@ static struct sis5595_data *sis5595_update_device(struct device *dev)
 
 		for (i = 0; i <= data->maxins; i++) {
 			data->in[i] =
-			    sis5595_read_value(client, SIS5595_REG_IN(i));
+			    sis5595_read_value(data, SIS5595_REG_IN(i));
 			data->in_min[i] =
-			    sis5595_read_value(client,
+			    sis5595_read_value(data,
 					       SIS5595_REG_IN_MIN(i));
 			data->in_max[i] =
-			    sis5595_read_value(client,
+			    sis5595_read_value(data,
 					       SIS5595_REG_IN_MAX(i));
 		}
 		for (i = 0; i < 2; i++) {
 			data->fan[i] =
-			    sis5595_read_value(client, SIS5595_REG_FAN(i));
+			    sis5595_read_value(data, SIS5595_REG_FAN(i));
 			data->fan_min[i] =
-			    sis5595_read_value(client,
+			    sis5595_read_value(data,
 					       SIS5595_REG_FAN_MIN(i));
 		}
 		if (data->maxins == 3) {
 			data->temp =
-			    sis5595_read_value(client, SIS5595_REG_TEMP);
+			    sis5595_read_value(data, SIS5595_REG_TEMP);
 			data->temp_over =
-			    sis5595_read_value(client, SIS5595_REG_TEMP_OVER);
+			    sis5595_read_value(data, SIS5595_REG_TEMP_OVER);
 			data->temp_hyst =
-			    sis5595_read_value(client, SIS5595_REG_TEMP_HYST);
+			    sis5595_read_value(data, SIS5595_REG_TEMP_HYST);
 		}
-		i = sis5595_read_value(client, SIS5595_REG_FANDIV);
+		i = sis5595_read_value(data, SIS5595_REG_FANDIV);
 		data->fan_div[0] = (i >> 4) & 0x03;
 		data->fan_div[1] = i >> 6;
 		data->alarms =
-		    sis5595_read_value(client, SIS5595_REG_ALARM1) |
-		    (sis5595_read_value(client, SIS5595_REG_ALARM2) << 8);
+		    sis5595_read_value(data, SIS5595_REG_ALARM1) |
+		    (sis5595_read_value(data, SIS5595_REG_ALARM2) << 8);
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -774,10 +692,50 @@ static int blacklist[] __devinitdata = {
 	PCI_DEVICE_ID_SI_5598,
 	0 };
 
+static int __devinit sis5595_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + SIS5595_EXTENT - 1,
+		.name	= "sis5595",
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc("sis5595", address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR "sis5595: Device allocation failed\n");
+		goto exit;
+	}
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR "sis5595: Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR "sis5595: Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
 static int __devinit sis5595_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *id)
 {
-	u16 val;
+	u16 address;
+	u8 enable;
 	int *i;
 
 	for (i = blacklist; *i != 0; i++) {
@@ -790,27 +748,68 @@ static int __devinit sis5595_pci_probe(struct pci_dev *dev,
 		}
 	}
 	
+	force_addr &= ~(SIS5595_EXTENT - 1);
+	if (force_addr) {
+		dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", force_addr);
+		pci_write_config_word(dev, SIS5595_BASE_REG, force_addr);
+	}
+
 	if (PCIBIOS_SUCCESSFUL !=
-	    pci_read_config_word(dev, SIS5595_BASE_REG, &val))
+	    pci_read_config_word(dev, SIS5595_BASE_REG, &address)) {
+		dev_err(&dev->dev, "Failed to read ISA address\n");
 		return -ENODEV;
+	}
 	
-	address = val & ~(SIS5595_EXTENT - 1);
-	if (address == 0 && force_addr == 0) {
+	address &= ~(SIS5595_EXTENT - 1);
+	if (!address) {
 		dev_err(&dev->dev, "Base address not set - upgrade BIOS or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
+	if (force_addr && address != force_addr) {
+		/* doesn't work for some chips? */
+		dev_err(&dev->dev, "Failed to force ISA address\n");
+		return -ENODEV;
+	}
 
-	s_bridge = pci_dev_get(dev);
-	if (i2c_isa_add_driver(&sis5595_driver)) {
-		pci_dev_put(s_bridge);
-		s_bridge = NULL;
+	if (PCIBIOS_SUCCESSFUL !=
+	    pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable)) {
+		dev_err(&dev->dev, "Failed to read enable register\n");
+		return -ENODEV;
+	}
+	if (!(enable & 0x80)) {
+		if ((PCIBIOS_SUCCESSFUL !=
+		     pci_write_config_byte(dev, SIS5595_ENABLE_REG,
+					   enable | 0x80))
+		 || (PCIBIOS_SUCCESSFUL !=
+		     pci_read_config_byte(dev, SIS5595_ENABLE_REG, &enable))
+		 || (!(enable & 0x80))) {
+			/* doesn't work for some chips! */
+			dev_err(&dev->dev, "Failed to enable HWM device\n");
+			return -ENODEV;
+		}
 	}
 
+	if (platform_driver_register(&sis5595_driver)) {
+		dev_dbg(&dev->dev, "Failed to register sis5595 driver\n");
+		goto exit;
+	}
+
+	s_bridge = pci_dev_get(dev);
+	/* Sets global pdev as a side effect */
+	if (sis5595_device_add(address))
+		goto exit_unregister;
+
 	/* Always return failure here.  This is to allow other drivers to bind
 	 * to this pci device.  We don't really want to have control over the
 	 * pci device, we only wanted to read as few register values from it.
 	 */
 	return -ENODEV;
+
+exit_unregister:
+	pci_dev_put(dev);
+	platform_driver_unregister(&sis5595_driver);
+exit:
+	return -ENODEV;
 }
 
 static struct pci_driver sis5595_pci_driver = {
@@ -828,7 +827,8 @@ static void __exit sm_sis5595_exit(void)
 {
 	pci_unregister_driver(&sis5595_pci_driver);
 	if (s_bridge != NULL) {
-		i2c_isa_del_driver(&sis5595_driver);
+		platform_device_unregister(pdev);
+		platform_driver_unregister(&sis5595_driver);
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
diff --git a/drivers/hwmon/smsc47b397.c b/drivers/hwmon/smsc47b397.c
index 943abbd95ab5..45266b30ce1d 100644
--- a/drivers/hwmon/smsc47b397.c
+++ b/drivers/hwmon/smsc47b397.c
@@ -174,6 +174,8 @@ static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp, NULL, 3);
    REG: count of 90kHz pulses / revolution */
 static int fan_from_reg(u16 reg)
 {
+	if (reg == 0 || reg == 0xffff)
+		return 0;
 	return 90000 * 60 / reg;
 }
 
@@ -333,7 +335,7 @@ static int __init smsc47b397_find(unsigned short *addr)
 	superio_enter();
 	id = superio_inb(SUPERIO_REG_DEVID);
 
-	if ((id != 0x6f) && (id != 0x81)) {
+	if ((id != 0x6f) && (id != 0x81) && (id != 0x85)) {
 		superio_exit();
 		return -ENODEV;
 	}
@@ -346,7 +348,8 @@ static int __init smsc47b397_find(unsigned short *addr)
 
 	printk(KERN_INFO DRVNAME ": found SMSC %s "
 		"(base address 0x%04x, revision %u)\n",
-		id == 0x81 ? "SCH5307-NS" : "LPC47B397-NC", *addr, rev);
+		id == 0x81 ? "SCH5307-NS" : id == 0x85 ? "SCH5317" :
+	       "LPC47B397-NC", *addr, rev);
 
 	superio_exit();
 	return 0;
diff --git a/drivers/hwmon/smsc47m1.c b/drivers/hwmon/smsc47m1.c
index 1e21c8cc948f..d3181967f167 100644
--- a/drivers/hwmon/smsc47m1.c
+++ b/drivers/hwmon/smsc47m1.c
@@ -134,7 +134,7 @@ struct smsc47m1_sio_data {
 
 
 static int smsc47m1_probe(struct platform_device *pdev);
-static int smsc47m1_remove(struct platform_device *pdev);
+static int __devexit smsc47m1_remove(struct platform_device *pdev);
 static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 		int init);
 
@@ -585,6 +585,8 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
 
 	if ((err = device_create_file(dev, &dev_attr_alarms)))
 		goto error_remove_files;
+	if ((err = device_create_file(dev, &dev_attr_name)))
+		goto error_remove_files;
 
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
@@ -597,6 +599,7 @@ static int __devinit smsc47m1_probe(struct platform_device *pdev)
 error_remove_files:
 	sysfs_remove_group(&dev->kobj, &smsc47m1_group);
 error_free:
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 error_release:
 	release_region(res->start, SMSC_EXTENT);
@@ -608,12 +611,12 @@ static int __devexit smsc47m1_remove(struct platform_device *pdev)
 	struct smsc47m1_data *data = platform_get_drvdata(pdev);
 	struct resource *res;
 
-	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
 	sysfs_remove_group(&pdev->dev.kobj, &smsc47m1_group);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	release_region(res->start, SMSC_EXTENT);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
@@ -693,15 +696,12 @@ static int __init smsc47m1_device_add(unsigned short address,
 		goto exit_device_put;
 	}
 
-	pdev->dev.platform_data = kmalloc(sizeof(struct smsc47m1_sio_data),
-					  GFP_KERNEL);
-	if (!pdev->dev.platform_data) {
-		err = -ENOMEM;
+	err = platform_device_add_data(pdev, sio_data,
+				       sizeof(struct smsc47m1_sio_data));
+	if (err) {
 		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
 		goto exit_device_put;
 	}
-	memcpy(pdev->dev.platform_data, sio_data,
-	       sizeof(struct smsc47m1_sio_data));
 
 	err = platform_device_add(pdev);
 	if (err) {
diff --git a/drivers/hwmon/smsc47m192.c b/drivers/hwmon/smsc47m192.c
index a012f396f354..d3a3ba04cb0f 100644
--- a/drivers/hwmon/smsc47m192.c
+++ b/drivers/hwmon/smsc47m192.c
@@ -31,6 +31,7 @@
 #include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/sysfs.h>
+#include <linux/mutex.h>
 
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x2c, 0x2d, I2C_CLIENT_END };
@@ -97,7 +98,7 @@ static inline int TEMP_FROM_REG(s8 val)
 struct smsc47m192_data {
 	struct i2c_client client;
 	struct class_device *class_dev;
-	struct semaphore update_lock;
+	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
@@ -164,11 +165,11 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
-	down(&data->update_lock);
+	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val, nr);
 	i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MIN(nr),
 							data->in_min[nr]);
-	up(&data->update_lock);
+	mutex_unlock(&data->update_lock);
 	return count;
 }
 
@@ -181,11 +182,11 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
-	down(&data->update_lock);
+	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val, nr);
 	i2c_smbus_write_byte_data(client, SMSC47M192_REG_IN_MAX(nr),
 							data->in_max[nr]);
-	up(&data->update_lock);
+	mutex_unlock(&data->update_lock);
 	return count;
 }
 
@@ -243,11 +244,11 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
 	long val = simple_strtol(buf, NULL, 10);
 
-	down(&data->update_lock);
+	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = TEMP_TO_REG(val);
 	i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MIN[nr],
 						data->temp_min[nr]);
-	up(&data->update_lock);
+	mutex_unlock(&data->update_lock);
 	return count;
 }
 
@@ -260,11 +261,11 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
 	long val = simple_strtol(buf, NULL, 10);
 
-	down(&data->update_lock);
+	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = TEMP_TO_REG(val);
 	i2c_smbus_write_byte_data(client, SMSC47M192_REG_TEMP_MAX[nr],
 						data->temp_max[nr]);
-	up(&data->update_lock);
+	mutex_unlock(&data->update_lock);
 	return count;
 }
 
@@ -287,7 +288,7 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute
 	u8 sfr = i2c_smbus_read_byte_data(client, SMSC47M192_REG_SFR);
 	long val = simple_strtol(buf, NULL, 10);
 
-	down(&data->update_lock);
+	mutex_lock(&data->update_lock);
 	data->temp_offset[nr] = TEMP_TO_REG(val);
 	if (nr>1)
 		i2c_smbus_write_byte_data(client,
@@ -303,7 +304,7 @@ static ssize_t set_temp_offset(struct device *dev, struct device_attribute
 	} else if ((sfr & 0x10) == (nr==0 ? 0x10 : 0))
 		i2c_smbus_write_byte_data(client,
 					SMSC47M192_REG_TEMP_OFFSET(nr), 0);
-	up(&data->update_lock);
+	mutex_unlock(&data->update_lock);
 	return count;
 }
 
@@ -360,8 +361,8 @@ static ssize_t show_alarm(struct device *dev, struct device_attribute *attr,
 static SENSOR_DEVICE_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 0x0010);
 static SENSOR_DEVICE_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 0x0020);
 static SENSOR_DEVICE_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 0x0040);
-static SENSOR_DEVICE_ATTR(temp2_input_fault, S_IRUGO, show_alarm, NULL, 0x4000);
-static SENSOR_DEVICE_ATTR(temp3_input_fault, S_IRUGO, show_alarm, NULL, 0x8000);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_alarm, NULL, 0x4000);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_alarm, NULL, 0x8000);
 static SENSOR_DEVICE_ATTR(in0_alarm, S_IRUGO, show_alarm, NULL, 0x0001);
 static SENSOR_DEVICE_ATTR(in1_alarm, S_IRUGO, show_alarm, NULL, 0x0002);
 static SENSOR_DEVICE_ATTR(in2_alarm, S_IRUGO, show_alarm, NULL, 0x0004);
@@ -411,13 +412,13 @@ static struct attribute *smsc47m192_attributes[] = {
 	&sensor_dev_attr_temp2_min.dev_attr.attr,
 	&sensor_dev_attr_temp2_offset.dev_attr.attr,
 	&sensor_dev_attr_temp2_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp2_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
 	&sensor_dev_attr_temp3_input.dev_attr.attr,
 	&sensor_dev_attr_temp3_max.dev_attr.attr,
 	&sensor_dev_attr_temp3_min.dev_attr.attr,
 	&sensor_dev_attr_temp3_offset.dev_attr.attr,
 	&sensor_dev_attr_temp3_alarm.dev_attr.attr,
-	&sensor_dev_attr_temp3_input_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
 
 	&dev_attr_cpu0_vid.attr,
 	&dev_attr_vrm.attr,
@@ -531,7 +532,7 @@ static int smsc47m192_detect(struct i2c_adapter *adapter, int address,
 	/* Fill in the remaining client fields and put into the global list */
 	strlcpy(client->name, "smsc47m192", I2C_NAME_SIZE);
 	data->vrm = vid_which_vrm();
-	init_MUTEX(&data->update_lock);
+	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(client)))
@@ -594,7 +595,7 @@ static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
 	struct smsc47m192_data *data = i2c_get_clientdata(client);
 	int i, config;
 
-	down(&data->update_lock);
+	mutex_lock(&data->update_lock);
 
 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 	 || !data->valid) {
@@ -645,7 +646,7 @@ static struct smsc47m192_data *smsc47m192_update_device(struct device *dev)
 		data->valid = 1;
 	}
 
-	up(&data->update_lock);
+	mutex_unlock(&data->update_lock);
 
 	return data;
 }
diff --git a/drivers/hwmon/thmc50.c b/drivers/hwmon/thmc50.c
new file mode 100644
index 000000000000..9395b52d9b99
--- /dev/null
+++ b/drivers/hwmon/thmc50.c
@@ -0,0 +1,440 @@
+/*
+    thmc50.c - Part of lm_sensors, Linux kernel modules for hardware
+             monitoring
+    Copyright (C) 2007 Krzysztof Helt <krzysztof.h1@wp.pl>
+    Based on 2.4 driver by Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com>
+
+    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/i2c.h>
+#include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
+#include <linux/err.h>
+#include <linux/mutex.h>
+
+MODULE_LICENSE("GPL");
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2c, 0x2d, 0x2e, I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_2(thmc50, adm1022);
+I2C_CLIENT_MODULE_PARM(adm1022_temp3, "List of adapter,address pairs "
+			"to enable 3rd temperature (ADM1022 only)");
+
+/* Many THMC50 constants specified below */
+
+/* The THMC50 registers */
+#define THMC50_REG_CONF				0x40
+#define THMC50_REG_COMPANY_ID			0x3E
+#define THMC50_REG_DIE_CODE			0x3F
+#define THMC50_REG_ANALOG_OUT			0x19
+
+const static u8 THMC50_REG_TEMP[] = { 0x27, 0x26, 0x20 };
+const static u8 THMC50_REG_TEMP_MIN[] = { 0x3A, 0x38, 0x2C };
+const static u8 THMC50_REG_TEMP_MAX[] = { 0x39, 0x37, 0x2B };
+
+#define THMC50_REG_CONF_nFANOFF			0x20
+
+/* Each client has this additional data */
+struct thmc50_data {
+	struct i2c_client client;
+	struct class_device *class_dev;
+
+	struct mutex update_lock;
+	enum chips type;
+	unsigned long last_updated;	/* In jiffies */
+	char has_temp3;		/* !=0 if it is ADM1022 in temp3 mode */
+	char valid;		/* !=0 if following fields are valid */
+
+	/* Register values */
+	s8 temp_input[3];
+	s8 temp_max[3];
+	s8 temp_min[3];
+	u8 analog_out;
+};
+
+static int thmc50_attach_adapter(struct i2c_adapter *adapter);
+static int thmc50_detach_client(struct i2c_client *client);
+static void thmc50_init_client(struct i2c_client *client);
+static struct thmc50_data *thmc50_update_device(struct device *dev);
+
+static struct i2c_driver thmc50_driver = {
+	.driver = {
+		.name = "thmc50",
+	},
+	.attach_adapter = thmc50_attach_adapter,
+	.detach_client = thmc50_detach_client,
+};
+
+static ssize_t show_analog_out(struct device *dev,
+			       struct device_attribute *attr, char *buf)
+{
+	struct thmc50_data *data = thmc50_update_device(dev);
+	return sprintf(buf, "%d\n", data->analog_out);
+}
+
+static ssize_t set_analog_out(struct device *dev,
+			      struct device_attribute *attr,
+			      const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct thmc50_data *data = i2c_get_clientdata(client);
+	int tmp = simple_strtoul(buf, NULL, 10);
+	int config;
+
+	mutex_lock(&data->update_lock);
+	data->analog_out = SENSORS_LIMIT(tmp, 0, 255);
+	i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT,
+				  data->analog_out);
+
+	config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+	if (data->analog_out == 0)
+		config &= ~THMC50_REG_CONF_nFANOFF;
+	else
+		config |= THMC50_REG_CONF_nFANOFF;
+	i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+/* There is only one PWM mode = DC */
+static ssize_t show_pwm_mode(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	return sprintf(buf, "0\n");
+}
+
+/* Temperatures */
+static ssize_t show_temp(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct thmc50_data *data = thmc50_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_input[nr] * 1000);
+}
+
+static ssize_t show_temp_min(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct thmc50_data *data = thmc50_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_min[nr] * 1000);
+}
+
+static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct thmc50_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp_min[nr] = SENSORS_LIMIT(val / 1000, -128, 127);
+	i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MIN[nr],
+				  data->temp_min[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+static ssize_t show_temp_max(struct device *dev, struct device_attribute *attr,
+			     char *buf)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct thmc50_data *data = thmc50_update_device(dev);
+	return sprintf(buf, "%d\n", data->temp_max[nr] * 1000);
+}
+
+static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
+			    const char *buf, size_t count)
+{
+	int nr = to_sensor_dev_attr(attr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct thmc50_data *data = i2c_get_clientdata(client);
+	int val = simple_strtol(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+	data->temp_max[nr] = SENSORS_LIMIT(val / 1000, -128, 127);
+	i2c_smbus_write_byte_data(client, THMC50_REG_TEMP_MAX[nr],
+				  data->temp_max[nr]);
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+#define temp_reg(offset)						\
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp,	\
+			NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IRUGO | S_IWUSR,	\
+			show_temp_min, set_temp_min, offset - 1);	\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+			show_temp_max, set_temp_max, offset - 1);
+
+temp_reg(1);
+temp_reg(2);
+temp_reg(3);
+
+static SENSOR_DEVICE_ATTR(pwm1, S_IRUGO | S_IWUSR, show_analog_out,
+			  set_analog_out, 0);
+static SENSOR_DEVICE_ATTR(pwm1_mode, S_IRUGO, show_pwm_mode, NULL, 0);
+
+static struct attribute *thmc50_attributes[] = {
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_pwm1.dev_attr.attr,
+	&sensor_dev_attr_pwm1_mode.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group thmc50_group = {
+	.attrs = thmc50_attributes,
+};
+
+/* for ADM1022 3rd temperature mode */
+static struct attribute *adm1022_attributes[] = {
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_min.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group adm1022_group = {
+	.attrs = adm1022_attributes,
+};
+
+static int thmc50_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	unsigned company;
+	unsigned revision;
+	unsigned config;
+	struct i2c_client *client;
+	struct thmc50_data *data;
+	struct device *dev;
+	int err = 0;
+	const char *type_name = "";
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		pr_debug("thmc50: detect failed, "
+			 "smbus byte data not supported!\n");
+		goto exit;
+	}
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet.
+	   But it allows us to access thmc50 registers. */
+	if (!(data = kzalloc(sizeof(struct thmc50_data), GFP_KERNEL))) {
+		pr_debug("thmc50: detect failed, kzalloc failed!\n");
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	client = &data->client;
+	i2c_set_clientdata(client, data);
+	client->addr = address;
+	client->adapter = adapter;
+	client->driver = &thmc50_driver;
+	dev = &client->dev;
+
+	pr_debug("thmc50: Probing for THMC50 at 0x%2X on bus %d\n",
+		 client->addr, i2c_adapter_id(client->adapter));
+
+	/* Now, we do the remaining detection. */
+	company = i2c_smbus_read_byte_data(client, THMC50_REG_COMPANY_ID);
+	revision = i2c_smbus_read_byte_data(client, THMC50_REG_DIE_CODE);
+	config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+
+	if (kind == 0)
+		kind = thmc50;
+	else if (kind < 0) {
+		err = -ENODEV;
+		if (revision >= 0xc0 && ((config & 0x10) == 0)) {
+			if (company == 0x49) {
+				kind = thmc50;
+				err = 0;
+			} else if (company == 0x41) {
+				kind = adm1022;
+				err = 0;
+			}
+		}
+	}
+	if (err == -ENODEV) {
+		pr_debug("thmc50: Detection of THMC50/ADM1022 failed\n");
+		goto exit_free;
+	}
+	pr_debug("thmc50: Detected %s (version %x, revision %x)\n",
+		 type_name, (revision >> 4) - 0xc, revision & 0xf);
+	data->type = kind;
+
+	if (kind == thmc50)
+		type_name = "thmc50";
+	else if (kind == adm1022) {
+		int id = i2c_adapter_id(client->adapter);
+		int i;
+
+		type_name = "adm1022";
+		data->has_temp3 = (config >> 7) & 1;	/* config MSB */
+		for (i = 0; i + 1 < adm1022_temp3_num; i += 2)
+			if (adm1022_temp3[i] == id &&
+			    adm1022_temp3[i + 1] == address) {
+				/* enable 2nd remote temp */
+				data->has_temp3 = 1;
+				break;
+			}
+	}
+
+	/* Fill in the remaining client fields & put it into the global list */
+	strlcpy(client->name, type_name, I2C_NAME_SIZE);
+	mutex_init(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(client)))
+		goto exit_free;
+
+	thmc50_init_client(client);
+
+	/* Register sysfs hooks */
+	if ((err = sysfs_create_group(&client->dev.kobj, &thmc50_group)))
+		goto exit_detach;
+
+	/* Register ADM1022 sysfs hooks */
+	if (data->type == adm1022)
+		if ((err = sysfs_create_group(&client->dev.kobj,
+					      &adm1022_group)))
+			goto exit_remove_sysfs_thmc50;
+
+	/* Register a new directory entry with module sensors */
+	data->class_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->class_dev)) {
+		err = PTR_ERR(data->class_dev);
+		goto exit_remove_sysfs;
+	}
+
+	return 0;
+
+exit_remove_sysfs:
+	if (data->type == adm1022)
+		sysfs_remove_group(&client->dev.kobj, &adm1022_group);
+exit_remove_sysfs_thmc50:
+	sysfs_remove_group(&client->dev.kobj, &thmc50_group);
+exit_detach:
+	i2c_detach_client(client);
+exit_free:
+	kfree(data);
+exit:
+	return err;
+}
+
+static int thmc50_attach_adapter(struct i2c_adapter *adapter)
+{
+	if (!(adapter->class & I2C_CLASS_HWMON))
+		return 0;
+	return i2c_probe(adapter, &addr_data, thmc50_detect);
+}
+
+static int thmc50_detach_client(struct i2c_client *client)
+{
+	struct thmc50_data *data = i2c_get_clientdata(client);
+	int err;
+
+	hwmon_device_unregister(data->class_dev);
+	sysfs_remove_group(&client->dev.kobj, &thmc50_group);
+	if (data->type == adm1022)
+		sysfs_remove_group(&client->dev.kobj, &adm1022_group);
+
+	if ((err = i2c_detach_client(client)))
+		return err;
+
+	kfree(data);
+
+	return 0;
+}
+
+static void thmc50_init_client(struct i2c_client *client)
+{
+	struct thmc50_data *data = i2c_get_clientdata(client);
+	int config;
+
+	data->analog_out = i2c_smbus_read_byte_data(client,
+						    THMC50_REG_ANALOG_OUT);
+	/* set up to at least 1 */
+	if (data->analog_out == 0) {
+		data->analog_out = 1;
+		i2c_smbus_write_byte_data(client, THMC50_REG_ANALOG_OUT,
+					  data->analog_out);
+	}
+	config = i2c_smbus_read_byte_data(client, THMC50_REG_CONF);
+	config |= 0x1;	/* start the chip if it is in standby mode */
+	if (data->has_temp3)
+		config |= 0x80;		/* enable 2nd remote temp */
+	i2c_smbus_write_byte_data(client, THMC50_REG_CONF, config);
+}
+
+static struct thmc50_data *thmc50_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct thmc50_data *data = i2c_get_clientdata(client);
+	int timeout = HZ / 5 + (data->type == thmc50 ? HZ : 0);
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + timeout)
+	    || !data->valid) {
+
+		int temps = data->has_temp3 ? 3 : 2;
+		int i;
+		for (i = 0; i < temps; i++) {
+			data->temp_input[i] = i2c_smbus_read_byte_data(client,
+						THMC50_REG_TEMP[i]);
+			data->temp_max[i] = i2c_smbus_read_byte_data(client,
+						THMC50_REG_TEMP_MAX[i]);
+			data->temp_min[i] = i2c_smbus_read_byte_data(client,
+						THMC50_REG_TEMP_MIN[i]);
+		}
+		data->analog_out =
+		    i2c_smbus_read_byte_data(client, THMC50_REG_ANALOG_OUT);
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static int __init sm_thmc50_init(void)
+{
+	return i2c_add_driver(&thmc50_driver);
+}
+
+static void __exit sm_thmc50_exit(void)
+{
+	i2c_del_driver(&thmc50_driver);
+}
+
+MODULE_AUTHOR("Krzysztof Helt <krzysztof.h1@wp.pl>");
+MODULE_DESCRIPTION("THMC50 driver");
+
+module_init(sm_thmc50_init);
+module_exit(sm_thmc50_exit);
diff --git a/drivers/hwmon/via686a.c b/drivers/hwmon/via686a.c
index 9a440c8cc520..696c8a2e5374 100644
--- a/drivers/hwmon/via686a.c
+++ b/drivers/hwmon/via686a.c
@@ -34,9 +34,9 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
@@ -51,10 +51,7 @@ module_param(force_addr, ushort, 0);
 MODULE_PARM_DESC(force_addr,
 		 "Initialize the base address of the sensors");
 
-/* Device address
-   Note that we can't determine the ISA address until we have initialized
-   our module */
-static unsigned short address;
+static struct platform_device *pdev;
 
 /*
    The Via 686a southbridge has a LM78-like chip integrated on the same IC.
@@ -295,7 +292,8 @@ static inline long TEMP_FROM_REG10(u16 val)
 /* For each registered chip, we need to keep some data in memory.
    The structure is dynamically allocated. */
 struct via686a_data {
-	struct i2c_client client;
+	unsigned short addr;
+	const char *name;
 	struct class_device *class_dev;
 	struct mutex update_lock;
 	char valid;		/* !=0 if following fields are valid */
@@ -315,98 +313,85 @@ struct via686a_data {
 
 static struct pci_dev *s_bridge;	/* pointer to the (only) via686a */
 
-static int via686a_detect(struct i2c_adapter *adapter);
-static int via686a_detach_client(struct i2c_client *client);
+static int via686a_probe(struct platform_device *pdev);
+static int __devexit via686a_remove(struct platform_device *pdev);
 
-static inline int via686a_read_value(struct i2c_client *client, u8 reg)
+static inline int via686a_read_value(struct via686a_data *data, u8 reg)
 {
-	return (inb_p(client->addr + reg));
+	return inb_p(data->addr + reg);
 }
 
-static inline void via686a_write_value(struct i2c_client *client, u8 reg,
+static inline void via686a_write_value(struct via686a_data *data, u8 reg,
 				       u8 value)
 {
-	outb_p(value, client->addr + reg);
+	outb_p(value, data->addr + reg);
 }
 
 static struct via686a_data *via686a_update_device(struct device *dev);
-static void via686a_init_client(struct i2c_client *client);
+static void via686a_init_device(struct via686a_data *data);
 
 /* following are the sysfs callback functions */
 
 /* 7 voltage sensors */
-static ssize_t show_in(struct device *dev, char *buf, int nr) {
+static ssize_t show_in(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in[nr], nr));
 }
 
-static ssize_t show_in_min(struct device *dev, char *buf, int nr) {
+static ssize_t show_in_min(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_min[nr], nr));
 }
 
-static ssize_t show_in_max(struct device *dev, char *buf, int nr) {
+static ssize_t show_in_max(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%ld\n", IN_FROM_REG(data->in_max[nr], nr));
 }
 
-static ssize_t set_in_min(struct device *dev, const char *buf,
-		size_t count, int nr) {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+static ssize_t set_in_min(struct device *dev, struct device_attribute *da,
+		const char *buf, size_t count) {
+	struct via686a_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = IN_TO_REG(val, nr);
-	via686a_write_value(client, VIA686A_REG_IN_MIN(nr),
+	via686a_write_value(data, VIA686A_REG_IN_MIN(nr),
 			data->in_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_in_max(struct device *dev, const char *buf,
-		size_t count, int nr) {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+static ssize_t set_in_max(struct device *dev, struct device_attribute *da,
+		const char *buf, size_t count) {
+	struct via686a_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = IN_TO_REG(val, nr);
-	via686a_write_value(client, VIA686A_REG_IN_MAX(nr),
+	via686a_write_value(data, VIA686A_REG_IN_MAX(nr),
 			data->in_max[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 #define show_in_offset(offset)					\
-static ssize_t 							\
-	show_in##offset (struct device *dev, struct device_attribute *attr, char *buf)		\
-{								\
-	return show_in(dev, buf, offset);			\
-}								\
-static ssize_t 							\
-	show_in##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
-{								\
-	return show_in_min(dev, buf, offset);		\
-}								\
-static ssize_t 							\
-	show_in##offset##_max (struct device *dev, struct device_attribute *attr, char *buf)	\
-{								\
-	return show_in_max(dev, buf, offset);		\
-}								\
-static ssize_t set_in##offset##_min (struct device *dev, struct device_attribute *attr, 	\
-		const char *buf, size_t count) 			\
-{								\
-	return set_in_min(dev, buf, count, offset);		\
-}								\
-static ssize_t set_in##offset##_max (struct device *dev, struct device_attribute *attr,	\
-			const char *buf, size_t count)		\
-{								\
-	return set_in_max(dev, buf, count, offset);		\
-}								\
-static DEVICE_ATTR(in##offset##_input, S_IRUGO, show_in##offset, NULL);\
-static DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, 	\
-		show_in##offset##_min, set_in##offset##_min);	\
-static DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, 	\
-		show_in##offset##_max, set_in##offset##_max);
+static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO,		\
+		show_in, NULL, offset);				\
+static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR,	\
+		show_in_min, set_in_min, offset);		\
+static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_in_max, set_in_max, offset);
 
 show_in_offset(0);
 show_in_offset(1);
@@ -415,150 +400,128 @@ show_in_offset(3);
 show_in_offset(4);
 
 /* 3 temperatures */
-static ssize_t show_temp(struct device *dev, char *buf, int nr) {
+static ssize_t show_temp(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%ld\n", TEMP_FROM_REG10(data->temp[nr]));
 }
-static ssize_t show_temp_over(struct device *dev, char *buf, int nr) {
+static ssize_t show_temp_over(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_over[nr]));
 }
-static ssize_t show_temp_hyst(struct device *dev, char *buf, int nr) {
+static ssize_t show_temp_hyst(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%ld\n", TEMP_FROM_REG(data->temp_hyst[nr]));
 }
-static ssize_t set_temp_over(struct device *dev, const char *buf,
-		size_t count, int nr) {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+static ssize_t set_temp_over(struct device *dev, struct device_attribute *da,
+		const char *buf, size_t count) {
+	struct via686a_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_over[nr] = TEMP_TO_REG(val);
-	via686a_write_value(client, VIA686A_REG_TEMP_OVER[nr],
+	via686a_write_value(data, VIA686A_REG_TEMP_OVER[nr],
 			    data->temp_over[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_temp_hyst(struct device *dev, const char *buf,
-		size_t count, int nr) {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+static ssize_t set_temp_hyst(struct device *dev, struct device_attribute *da,
+		const char *buf, size_t count) {
+	struct via686a_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_hyst[nr] = TEMP_TO_REG(val);
-	via686a_write_value(client, VIA686A_REG_TEMP_HYST[nr],
+	via686a_write_value(data, VIA686A_REG_TEMP_HYST[nr],
 			    data->temp_hyst[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 #define show_temp_offset(offset)					\
-static ssize_t show_temp_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_temp(dev, buf, offset - 1);				\
-}									\
-static ssize_t								\
-show_temp_##offset##_over (struct device *dev, struct device_attribute *attr, char *buf)		\
-{									\
-	return show_temp_over(dev, buf, offset - 1);			\
-}									\
-static ssize_t								\
-show_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, char *buf)		\
-{									\
-	return show_temp_hyst(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_temp_##offset##_over (struct device *dev, struct device_attribute *attr, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_temp_over(dev, buf, count, offset - 1);		\
-}									\
-static ssize_t set_temp_##offset##_hyst (struct device *dev, struct device_attribute *attr, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_temp_hyst(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(temp##offset##_input, S_IRUGO, show_temp_##offset, NULL);\
-static DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_over, set_temp_##offset##_over);	\
-static DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, 		\
-		show_temp_##offset##_hyst, set_temp_##offset##_hyst);
+static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO,		\
+		show_temp, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IRUGO | S_IWUSR,	\
+		show_temp_over, set_temp_over, offset - 1);		\
+static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR,	\
+		show_temp_hyst, set_temp_hyst, offset - 1);
 
 show_temp_offset(1);
 show_temp_offset(2);
 show_temp_offset(3);
 
 /* 2 Fans */
-static ssize_t show_fan(struct device *dev, char *buf, int nr) {
+static ssize_t show_fan(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", FAN_FROM_REG(data->fan[nr],
 				DIV_FROM_REG(data->fan_div[nr])) );
 }
-static ssize_t show_fan_min(struct device *dev, char *buf, int nr) {
+static ssize_t show_fan_min(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n",
 		FAN_FROM_REG(data->fan_min[nr], DIV_FROM_REG(data->fan_div[nr])) );
 }
-static ssize_t show_fan_div(struct device *dev, char *buf, int nr) {
+static ssize_t show_fan_div(struct device *dev, struct device_attribute *da,
+		char *buf) {
 	struct via686a_data *data = via686a_update_device(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	return sprintf(buf, "%d\n", DIV_FROM_REG(data->fan_div[nr]) );
 }
-static ssize_t set_fan_min(struct device *dev, const char *buf,
-		size_t count, int nr) {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+static ssize_t set_fan_min(struct device *dev, struct device_attribute *da,
+		const char *buf, size_t count) {
+	struct via686a_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-	via686a_write_value(client, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
+	via686a_write_value(data, VIA686A_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
-static ssize_t set_fan_div(struct device *dev, const char *buf,
-		size_t count, int nr) {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+static ssize_t set_fan_div(struct device *dev, struct device_attribute *da,
+		const char *buf, size_t count) {
+	struct via686a_data *data = dev_get_drvdata(dev);
+	struct sensor_device_attribute *attr = to_sensor_dev_attr(da);
+	int nr = attr->index;
 	int val = simple_strtol(buf, NULL, 10);
 	int old;
 
 	mutex_lock(&data->update_lock);
-	old = via686a_read_value(client, VIA686A_REG_FANDIV);
+	old = via686a_read_value(data, VIA686A_REG_FANDIV);
 	data->fan_div[nr] = DIV_TO_REG(val);
 	old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
-	via686a_write_value(client, VIA686A_REG_FANDIV, old);
+	via686a_write_value(data, VIA686A_REG_FANDIV, old);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 
 #define show_fan_offset(offset)						\
-static ssize_t show_fan_##offset (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan(dev, buf, offset - 1);				\
-}									\
-static ssize_t show_fan_##offset##_min (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan_min(dev, buf, offset - 1);			\
-}									\
-static ssize_t show_fan_##offset##_div (struct device *dev, struct device_attribute *attr, char *buf)	\
-{									\
-	return show_fan_div(dev, buf, offset - 1);			\
-}									\
-static ssize_t set_fan_##offset##_min (struct device *dev, struct device_attribute *attr, 		\
-	const char *buf, size_t count) 					\
-{									\
-	return set_fan_min(dev, buf, count, offset - 1);		\
-}									\
-static ssize_t set_fan_##offset##_div (struct device *dev, struct device_attribute *attr, 		\
-		const char *buf, size_t count) 				\
-{									\
-	return set_fan_div(dev, buf, count, offset - 1);		\
-}									\
-static DEVICE_ATTR(fan##offset##_input, S_IRUGO, show_fan_##offset, NULL);\
-static DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_min, set_fan_##offset##_min);	\
-static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, 		\
-		show_fan_##offset##_div, set_fan_##offset##_div);
+static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO,			\
+		show_fan, NULL, offset - 1);				\
+static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IRUGO | S_IWUSR,		\
+		show_fan_min, set_fan_min, offset - 1);			\
+static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR,		\
+		show_fan_div, set_fan_div, offset - 1);
 
 show_fan_offset(1);
 show_fan_offset(2);
@@ -570,41 +533,50 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr, ch
 }
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct via686a_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 static struct attribute *via686a_attributes[] = {
-	&dev_attr_in0_input.attr,
-	&dev_attr_in1_input.attr,
-	&dev_attr_in2_input.attr,
-	&dev_attr_in3_input.attr,
-	&dev_attr_in4_input.attr,
-	&dev_attr_in0_min.attr,
-	&dev_attr_in1_min.attr,
-	&dev_attr_in2_min.attr,
-	&dev_attr_in3_min.attr,
-	&dev_attr_in4_min.attr,
-	&dev_attr_in0_max.attr,
-	&dev_attr_in1_max.attr,
-	&dev_attr_in2_max.attr,
-	&dev_attr_in3_max.attr,
-	&dev_attr_in4_max.attr,
-
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp2_input.attr,
-	&dev_attr_temp3_input.attr,
-	&dev_attr_temp1_max.attr,
-	&dev_attr_temp2_max.attr,
-	&dev_attr_temp3_max.attr,
-	&dev_attr_temp1_max_hyst.attr,
-	&dev_attr_temp2_max_hyst.attr,
-	&dev_attr_temp3_max_hyst.attr,
-
-	&dev_attr_fan1_input.attr,
-	&dev_attr_fan2_input.attr,
-	&dev_attr_fan1_min.attr,
-	&dev_attr_fan2_min.attr,
-	&dev_attr_fan1_div.attr,
-	&dev_attr_fan2_div.attr,
+	&sensor_dev_attr_in0_input.dev_attr.attr,
+	&sensor_dev_attr_in1_input.dev_attr.attr,
+	&sensor_dev_attr_in2_input.dev_attr.attr,
+	&sensor_dev_attr_in3_input.dev_attr.attr,
+	&sensor_dev_attr_in4_input.dev_attr.attr,
+	&sensor_dev_attr_in0_min.dev_attr.attr,
+	&sensor_dev_attr_in1_min.dev_attr.attr,
+	&sensor_dev_attr_in2_min.dev_attr.attr,
+	&sensor_dev_attr_in3_min.dev_attr.attr,
+	&sensor_dev_attr_in4_min.dev_attr.attr,
+	&sensor_dev_attr_in0_max.dev_attr.attr,
+	&sensor_dev_attr_in1_max.dev_attr.attr,
+	&sensor_dev_attr_in2_max.dev_attr.attr,
+	&sensor_dev_attr_in3_max.dev_attr.attr,
+	&sensor_dev_attr_in4_max.dev_attr.attr,
+
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp3_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp2_max_hyst.dev_attr.attr,
+	&sensor_dev_attr_temp3_max_hyst.dev_attr.attr,
+
+	&sensor_dev_attr_fan1_input.dev_attr.attr,
+	&sensor_dev_attr_fan2_input.dev_attr.attr,
+	&sensor_dev_attr_fan1_min.dev_attr.attr,
+	&sensor_dev_attr_fan2_min.dev_attr.attr,
+	&sensor_dev_attr_fan1_div.dev_attr.attr,
+	&sensor_dev_attr_fan2_div.dev_attr.attr,
 
 	&dev_attr_alarms.attr,
+	&dev_attr_name.attr,
 	NULL
 };
 
@@ -612,58 +584,29 @@ static const struct attribute_group via686a_group = {
 	.attrs = via686a_attributes,
 };
 
-/* The driver. I choose to use type i2c_driver, as at is identical to both
-   smbus_driver and isa_driver, and clients could be of either kind */
-static struct i2c_driver via686a_driver = {
+static struct platform_driver via686a_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "via686a",
 	},
-	.attach_adapter	= via686a_detect,
-	.detach_client	= via686a_detach_client,
+	.probe		= via686a_probe,
+	.remove		= __devexit_p(via686a_remove),
 };
 
 
 /* This is called when the module is loaded */
-static int via686a_detect(struct i2c_adapter *adapter)
+static int __devinit via686a_probe(struct platform_device *pdev)
 {
-	struct i2c_client *new_client;
 	struct via686a_data *data;
-	int err = 0;
-	const char client_name[] = "via686a";
-	u16 val;
-
-	/* 8231 requires multiple of 256, we enforce that on 686 as well */
-	if (force_addr) {
-		address = force_addr & 0xFF00;
-		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
-			 address);
-		if (PCIBIOS_SUCCESSFUL !=
-		    pci_write_config_word(s_bridge, VIA686A_BASE_REG, address))
-			return -ENODEV;
-	}
-	if (PCIBIOS_SUCCESSFUL !=
-	    pci_read_config_word(s_bridge, VIA686A_ENABLE_REG, &val))
-		return -ENODEV;
-	if (!(val & 0x0001)) {
-		if (force_addr) {
-			dev_info(&adapter->dev, "enabling sensors\n");
-			if (PCIBIOS_SUCCESSFUL !=
-			    pci_write_config_word(s_bridge, VIA686A_ENABLE_REG,
-						  val | 0x0001))
-				return -ENODEV;
-		} else {
-			dev_warn(&adapter->dev, "sensors disabled - enable "
-				 "with force_addr=0x%x\n", address);
-			return -ENODEV;
-		}
-	}
+	struct resource *res;
+	int err;
 
 	/* Reserve the ISA region */
-	if (!request_region(address, VIA686A_EXTENT,
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start, VIA686A_EXTENT,
 			    via686a_driver.driver.name)) {
-		dev_err(&adapter->dev, "region 0x%x already in use!\n",
-			address);
+		dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n",
+			(unsigned long)res->start, (unsigned long)res->end);
 		return -ENODEV;
 	}
 
@@ -672,30 +615,19 @@ static int via686a_detect(struct i2c_adapter *adapter)
 		goto exit_release;
 	}
 
-	new_client = &data->client;
-	i2c_set_clientdata(new_client, data);
-	new_client->addr = address;
-	new_client->adapter = adapter;
-	new_client->driver = &via686a_driver;
-	new_client->flags = 0;
-
-	/* Fill in the remaining client fields and put into the global list */
-	strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
-
-	data->valid = 0;
+	platform_set_drvdata(pdev, data);
+	data->addr = res->start;
+	data->name = "via686a";
 	mutex_init(&data->update_lock);
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(new_client)))
-		goto exit_free;
 
 	/* Initialize the VIA686A chip */
-	via686a_init_client(new_client);
+	via686a_init_device(data);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&new_client->dev.kobj, &via686a_group)))
-		goto exit_detach;
+	if ((err = sysfs_create_group(&pdev->dev.kobj, &via686a_group)))
+		goto exit_free;
 
-	data->class_dev = hwmon_device_register(&new_client->dev);
+	data->class_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto exit_remove_files;
@@ -704,51 +636,46 @@ static int via686a_detect(struct i2c_adapter *adapter)
 	return 0;
 
 exit_remove_files:
-	sysfs_remove_group(&new_client->dev.kobj, &via686a_group);
-exit_detach:
-	i2c_detach_client(new_client);
+	sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
 exit_free:
 	kfree(data);
 exit_release:
-	release_region(address, VIA686A_EXTENT);
+	release_region(res->start, VIA686A_EXTENT);
 	return err;
 }
 
-static int via686a_detach_client(struct i2c_client *client)
+static int __devexit via686a_remove(struct platform_device *pdev)
 {
-	struct via686a_data *data = i2c_get_clientdata(client);
-	int err;
+	struct via686a_data *data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(data->class_dev);
-	sysfs_remove_group(&client->dev.kobj, &via686a_group);
+	sysfs_remove_group(&pdev->dev.kobj, &via686a_group);
 
-	if ((err = i2c_detach_client(client)))
-		return err;
-
-	release_region(client->addr, VIA686A_EXTENT);
+	release_region(data->addr, VIA686A_EXTENT);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
 }
 
-static void via686a_init_client(struct i2c_client *client)
+static void __devinit via686a_init_device(struct via686a_data *data)
 {
 	u8 reg;
 
 	/* Start monitoring */
-	reg = via686a_read_value(client, VIA686A_REG_CONFIG);
-	via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
+	reg = via686a_read_value(data, VIA686A_REG_CONFIG);
+	via686a_write_value(data, VIA686A_REG_CONFIG, (reg | 0x01) & 0x7F);
 
 	/* Configure temp interrupt mode for continuous-interrupt operation */
-	via686a_write_value(client, VIA686A_REG_TEMP_MODE,
-			    via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
-			    !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
+	reg = via686a_read_value(data, VIA686A_REG_TEMP_MODE);
+	via686a_write_value(data, VIA686A_REG_TEMP_MODE,
+			    (reg & ~VIA686A_TEMP_MODE_MASK)
+			    | VIA686A_TEMP_MODE_CONTINUOUS);
 }
 
 static struct via686a_data *via686a_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct via686a_data *data = i2c_get_clientdata(client);
+	struct via686a_data *data = dev_get_drvdata(dev);
 	int i;
 
 	mutex_lock(&data->update_lock);
@@ -757,27 +684,27 @@ static struct via686a_data *via686a_update_device(struct device *dev)
 	    || !data->valid) {
 		for (i = 0; i <= 4; i++) {
 			data->in[i] =
-			    via686a_read_value(client, VIA686A_REG_IN(i));
-			data->in_min[i] = via686a_read_value(client,
+			    via686a_read_value(data, VIA686A_REG_IN(i));
+			data->in_min[i] = via686a_read_value(data,
 							     VIA686A_REG_IN_MIN
 							     (i));
 			data->in_max[i] =
-			    via686a_read_value(client, VIA686A_REG_IN_MAX(i));
+			    via686a_read_value(data, VIA686A_REG_IN_MAX(i));
 		}
 		for (i = 1; i <= 2; i++) {
 			data->fan[i - 1] =
-			    via686a_read_value(client, VIA686A_REG_FAN(i));
-			data->fan_min[i - 1] = via686a_read_value(client,
+			    via686a_read_value(data, VIA686A_REG_FAN(i));
+			data->fan_min[i - 1] = via686a_read_value(data,
 						     VIA686A_REG_FAN_MIN(i));
 		}
 		for (i = 0; i <= 2; i++) {
-			data->temp[i] = via686a_read_value(client,
+			data->temp[i] = via686a_read_value(data,
 						 VIA686A_REG_TEMP[i]) << 2;
 			data->temp_over[i] =
-			    via686a_read_value(client,
+			    via686a_read_value(data,
 					       VIA686A_REG_TEMP_OVER[i]);
 			data->temp_hyst[i] =
-			    via686a_read_value(client,
+			    via686a_read_value(data,
 					       VIA686A_REG_TEMP_HYST[i]);
 		}
 		/* add in lower 2 bits
@@ -785,23 +712,23 @@ static struct via686a_data *via686a_update_device(struct device *dev)
 		   temp2 uses bits 5-4 of VIA686A_REG_TEMP_LOW23
 		   temp3 uses bits 7-6 of VIA686A_REG_TEMP_LOW23
 		 */
-		data->temp[0] |= (via686a_read_value(client,
+		data->temp[0] |= (via686a_read_value(data,
 						     VIA686A_REG_TEMP_LOW1)
 				  & 0xc0) >> 6;
 		data->temp[1] |=
-		    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
+		    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
 		     0x30) >> 4;
 		data->temp[2] |=
-		    (via686a_read_value(client, VIA686A_REG_TEMP_LOW23) &
+		    (via686a_read_value(data, VIA686A_REG_TEMP_LOW23) &
 		     0xc0) >> 6;
 
-		i = via686a_read_value(client, VIA686A_REG_FANDIV);
+		i = via686a_read_value(data, VIA686A_REG_FANDIV);
 		data->fan_div[0] = (i >> 4) & 0x03;
 		data->fan_div[1] = i >> 6;
 		data->alarms =
-		    via686a_read_value(client,
+		    via686a_read_value(data,
 				       VIA686A_REG_ALARM1) |
-		    (via686a_read_value(client, VIA686A_REG_ALARM2) << 8);
+		    (via686a_read_value(data, VIA686A_REG_ALARM2) << 8);
 		data->last_updated = jiffies;
 		data->valid = 1;
 	}
@@ -818,32 +745,102 @@ static struct pci_device_id via686a_pci_ids[] = {
 
 MODULE_DEVICE_TABLE(pci, via686a_pci_ids);
 
+static int __devinit via686a_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + VIA686A_EXTENT - 1,
+		.name	= "via686a",
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc("via686a", address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR "via686a: Device allocation failed\n");
+		goto exit;
+	}
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR "via686a: Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR "via686a: Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
 static int __devinit via686a_pci_probe(struct pci_dev *dev,
 				       const struct pci_device_id *id)
 {
-	u16 val;
+	u16 address, val;
 
+	if (force_addr) {
+		address = force_addr & ~(VIA686A_EXTENT - 1);
+		dev_warn(&dev->dev, "Forcing ISA address 0x%x\n", address);
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(dev, VIA686A_BASE_REG, address | 1))
+			return -ENODEV;
+	}
 	if (PCIBIOS_SUCCESSFUL !=
 	    pci_read_config_word(dev, VIA686A_BASE_REG, &val))
 		return -ENODEV;
 
 	address = val & ~(VIA686A_EXTENT - 1);
-	if (address == 0 && force_addr == 0) {
+	if (address == 0) {
 		dev_err(&dev->dev, "base address not set - upgrade BIOS "
 			"or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
 
-	s_bridge = pci_dev_get(dev);
-	if (i2c_isa_add_driver(&via686a_driver)) {
-		pci_dev_put(s_bridge);
-		s_bridge = NULL;
+	if (PCIBIOS_SUCCESSFUL !=
+	    pci_read_config_word(dev, VIA686A_ENABLE_REG, &val))
+		return -ENODEV;
+	if (!(val & 0x0001)) {
+		if (!force_addr) {
+			dev_warn(&dev->dev, "Sensors disabled, enable "
+				 "with force_addr=0x%x\n", address);
+			return -ENODEV;
+		}
+
+		dev_warn(&dev->dev, "Enabling sensors\n");
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(dev, VIA686A_ENABLE_REG,
+					  val | 0x0001))
+			return -ENODEV;
 	}
 
+	if (platform_driver_register(&via686a_driver))
+		goto exit;
+
+	/* Sets global pdev as a side effect */
+	if (via686a_device_add(address))
+		goto exit_unregister;
+
 	/* Always return failure here.  This is to allow other drivers to bind
 	 * to this pci device.  We don't really want to have control over the
 	 * pci device, we only wanted to read as few register values from it.
 	 */
+	s_bridge = pci_dev_get(dev);
+	return -ENODEV;
+
+exit_unregister:
+	platform_driver_unregister(&via686a_driver);
+exit:
 	return -ENODEV;
 }
 
@@ -862,7 +859,8 @@ static void __exit sm_via686a_exit(void)
 {
 	pci_unregister_driver(&via686a_pci_driver);
 	if (s_bridge != NULL) {
-		i2c_isa_del_driver(&via686a_driver);
+		platform_device_unregister(pdev);
+		platform_driver_unregister(&via686a_driver);
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
diff --git a/drivers/hwmon/vt8231.c b/drivers/hwmon/vt8231.c
index a6a4aa0eee16..3e63eaf19041 100644
--- a/drivers/hwmon/vt8231.c
+++ b/drivers/hwmon/vt8231.c
@@ -29,8 +29,7 @@
 #include <linux/slab.h>
 #include <linux/pci.h>
 #include <linux/jiffies.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-vid.h>
@@ -42,10 +41,7 @@ static int force_addr;
 module_param(force_addr, int, 0);
 MODULE_PARM_DESC(force_addr, "Initialize the base address of the sensors");
 
-/* Device address
-   Note that we can't determine the ISA address until we have initialized
-   our module */
-static unsigned short isa_address;
+static struct platform_device *pdev;
 
 #define VT8231_EXTENT 0x80
 #define VT8231_BASE_REG 0x70
@@ -148,7 +144,9 @@ static inline u8 FAN_TO_REG(long rpm, int div)
 #define FAN_FROM_REG(val, div) ((val) == 0 ? 0 : 1310720 / ((val) * (div)))
 
 struct vt8231_data {
-	struct i2c_client client;
+	unsigned short addr;
+	const char *name;
+
 	struct mutex update_lock;
 	struct class_device *class_dev;
 	char valid;		/* !=0 if following fields are valid */
@@ -168,20 +166,20 @@ struct vt8231_data {
 };
 
 static struct pci_dev *s_bridge;
-static int vt8231_detect(struct i2c_adapter *adapter);
-static int vt8231_detach_client(struct i2c_client *client);
+static int vt8231_probe(struct platform_device *pdev);
+static int __devexit vt8231_remove(struct platform_device *pdev);
 static struct vt8231_data *vt8231_update_device(struct device *dev);
-static void vt8231_init_client(struct i2c_client *client);
+static void vt8231_init_device(struct vt8231_data *data);
 
-static inline int vt8231_read_value(struct i2c_client *client, u8 reg)
+static inline int vt8231_read_value(struct vt8231_data *data, u8 reg)
 {
-	return inb_p(client->addr + reg);
+	return inb_p(data->addr + reg);
 }
 
-static inline void vt8231_write_value(struct i2c_client *client, u8 reg,
+static inline void vt8231_write_value(struct vt8231_data *data, u8 reg,
 					u8 value)
 {
-	outb_p(value, client->addr + reg);
+	outb_p(value, data->addr + reg);
 }
 
 /* following are the sysfs callback functions */
@@ -220,13 +218,12 @@ static ssize_t set_in_min(struct device *dev, struct device_attribute *attr,
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_min[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
-	vt8231_write_value(client, regvoltmin[nr], data->in_min[nr]);
+	vt8231_write_value(data, regvoltmin[nr], data->in_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -236,13 +233,12 @@ static ssize_t set_in_max(struct device *dev, struct device_attribute *attr,
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_max[nr] = SENSORS_LIMIT(((val * 958) / 10000) + 3, 0, 255);
-	vt8231_write_value(client, regvoltmax[nr], data->in_max[nr]);
+	vt8231_write_value(data, regvoltmax[nr], data->in_max[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -278,14 +274,13 @@ static ssize_t show_in5_max(struct device *dev, struct device_attribute *attr,
 static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_min[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
 					0, 255);
-	vt8231_write_value(client, regvoltmin[5], data->in_min[5]);
+	vt8231_write_value(data, regvoltmin[5], data->in_min[5]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -293,14 +288,13 @@ static ssize_t set_in5_min(struct device *dev, struct device_attribute *attr,
 static ssize_t set_in5_max(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->in_max[5] = SENSORS_LIMIT(((val * 958 * 34) / (10000 * 54)) + 3,
 					0, 255);
-	vt8231_write_value(client, regvoltmax[5], data->in_max[5]);
+	vt8231_write_value(data, regvoltmax[5], data->in_max[5]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -348,26 +342,24 @@ static ssize_t show_temp0_min(struct device *dev, struct device_attribute *attr,
 static ssize_t set_temp0_max(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
-	vt8231_write_value(client, regtempmax[0], data->temp_max[0]);
+	vt8231_write_value(data, regtempmax[0], data->temp_max[0]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
 static ssize_t set_temp0_min(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[0] = SENSORS_LIMIT((val + 500) / 1000, 0, 255);
-	vt8231_write_value(client, regtempmin[0], data->temp_min[0]);
+	vt8231_write_value(data, regtempmin[0], data->temp_min[0]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -404,13 +396,12 @@ static ssize_t set_temp_max(struct device *dev, struct device_attribute *attr,
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_max[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
-	vt8231_write_value(client, regtempmax[nr], data->temp_max[nr]);
+	vt8231_write_value(data, regtempmax[nr], data->temp_max[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -419,13 +410,12 @@ static ssize_t set_temp_min(struct device *dev, struct device_attribute *attr,
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	int val = simple_strtol(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->temp_min[nr] = SENSORS_LIMIT(TEMP_MAXMIN_TO_REG(val), 0, 255);
-	vt8231_write_value(client, regtempmin[nr], data->temp_min[nr]);
+	vt8231_write_value(data, regtempmin[nr], data->temp_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -486,13 +476,12 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 {
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	int val = simple_strtoul(buf, NULL, 10);
 
 	mutex_lock(&data->update_lock);
 	data->fan_min[nr] = FAN_TO_REG(val, DIV_FROM_REG(data->fan_div[nr]));
-	vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+	vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -500,12 +489,11 @@ static ssize_t set_fan_min(struct device *dev, struct device_attribute *attr,
 static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 		const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	unsigned long val = simple_strtoul(buf, NULL, 10);
 	int nr = sensor_attr->index;
-	int old = vt8231_read_value(client, VT8231_REG_FANDIV);
+	int old = vt8231_read_value(data, VT8231_REG_FANDIV);
 	long min = FAN_FROM_REG(data->fan_min[nr],
 				 DIV_FROM_REG(data->fan_div[nr]));
 
@@ -516,7 +504,7 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 	case 4: data->fan_div[nr] = 2; break;
 	case 8: data->fan_div[nr] = 3; break;
 	default:
-		dev_err(&client->dev, "fan_div value %ld not supported."
+		dev_err(dev, "fan_div value %ld not supported."
 		        "Choose one of 1, 2, 4 or 8!\n", val);
 		mutex_unlock(&data->update_lock);
 		return -EINVAL;
@@ -524,10 +512,10 @@ static ssize_t set_fan_div(struct device *dev, struct device_attribute *attr,
 
 	/* Correct the fan minimum speed */
 	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
-	vt8231_write_value(client, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
+	vt8231_write_value(data, VT8231_REG_FAN_MIN(nr), data->fan_min[nr]);
 
 	old = (old & 0x0f) | (data->fan_div[1] << 6) | (data->fan_div[0] << 4);
-	vt8231_write_value(client, VT8231_REG_FANDIV, old);
+	vt8231_write_value(data, VT8231_REG_FANDIV, old);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -551,9 +539,16 @@ static ssize_t show_alarms(struct device *dev, struct device_attribute *attr,
 	struct vt8231_data *data = vt8231_update_device(dev);
 	return sprintf(buf, "%d\n", data->alarms);
 }
-
 static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
+static ssize_t show_name(struct device *dev, struct device_attribute
+			 *devattr, char *buf)
+{
+	struct vt8231_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
+
 static struct attribute *vt8231_attributes_temps[6][4] = {
 	{
 		&dev_attr_temp1_input.attr,
@@ -648,6 +643,7 @@ static struct attribute *vt8231_attributes[] = {
 	&sensor_dev_attr_fan1_div.dev_attr.attr,
 	&sensor_dev_attr_fan2_div.dev_attr.attr,
 	&dev_attr_alarms.attr,
+	&dev_attr_name.attr,
 	NULL
 };
 
@@ -655,13 +651,13 @@ static const struct attribute_group vt8231_group = {
 	.attrs = vt8231_attributes,
 };
 
-static struct i2c_driver vt8231_driver = {
+static struct platform_driver vt8231_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
 		.name	= "vt8231",
 	},
-	.attach_adapter	= vt8231_detect,
-	.detach_client	= vt8231_detach_client,
+	.probe	= vt8231_probe,
+	.remove	= __devexit_p(vt8231_remove),
 };
 
 static struct pci_device_id vt8231_pci_ids[] = {
@@ -680,40 +676,18 @@ static struct pci_driver vt8231_pci_driver = {
 	.probe		= vt8231_pci_probe,
 };
 
-int vt8231_detect(struct i2c_adapter *adapter)
+int vt8231_probe(struct platform_device *pdev)
 {
-	struct i2c_client *client;
+	struct resource *res;
 	struct vt8231_data *data;
 	int err = 0, i;
-	u16 val;
-
-	/* 8231 requires multiple of 256 */
-	if (force_addr)	{
-		isa_address = force_addr & 0xFF00;
-		dev_warn(&adapter->dev, "forcing ISA address 0x%04X\n",
-				 isa_address);
-		if (PCIBIOS_SUCCESSFUL != pci_write_config_word(s_bridge,
-						VT8231_BASE_REG, isa_address))
-			return -ENODEV;
-	}
-
-	if (PCIBIOS_SUCCESSFUL !=
-		pci_read_config_word(s_bridge, VT8231_ENABLE_REG, &val))
-		return -ENODEV;
-
-	if (!(val & 0x0001)) {
-		dev_warn(&adapter->dev, "enabling sensors\n");
-		if (PCIBIOS_SUCCESSFUL !=
-			pci_write_config_word(s_bridge, VT8231_ENABLE_REG,
-							  val | 0x0001))
-			return -ENODEV;
-	}
 
 	/* Reserve the ISA region */
-	if (!request_region(isa_address, VT8231_EXTENT,
-			    vt8231_pci_driver.name)) {
-		dev_err(&adapter->dev, "region 0x%x already in use!\n",
-			   isa_address);
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start, VT8231_EXTENT,
+			    vt8231_driver.driver.name)) {
+		dev_err(&pdev->dev, "Region 0x%lx-0x%lx already in use!\n",
+			(unsigned long)res->start, (unsigned long)res->end);
 		return -ENODEV;
 	}
 
@@ -722,33 +696,23 @@ int vt8231_detect(struct i2c_adapter *adapter)
 		goto exit_release;
 	}
 
-	client = &data->client;
-	i2c_set_clientdata(client, data);
-	client->addr = isa_address;
-	client->adapter = adapter;
-	client->driver = &vt8231_driver;
-
-	/* Fill in the remaining client fields and put into the global list */
-	strlcpy(client->name, "vt8231", I2C_NAME_SIZE);
+	platform_set_drvdata(pdev, data);
+	data->addr = res->start;
+	data->name = "vt8231";
 
 	mutex_init(&data->update_lock);
-
-	/* Tell the I2C layer a new client has arrived */
-	if ((err = i2c_attach_client(client)))
-		goto exit_free;
-
-	vt8231_init_client(client);
+	vt8231_init_device(data);
 
 	/* Register sysfs hooks */
-	if ((err = sysfs_create_group(&client->dev.kobj, &vt8231_group)))
-		goto exit_detach;
+	if ((err = sysfs_create_group(&pdev->dev.kobj, &vt8231_group)))
+		goto exit_free;
 
 	/* Must update device information to find out the config field */
-	data->uch_config = vt8231_read_value(client, VT8231_REG_UCH_CONFIG);
+	data->uch_config = vt8231_read_value(data, VT8231_REG_UCH_CONFIG);
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++) {
 		if (ISTEMP(i, data->uch_config)) {
-			if ((err = sysfs_create_group(&client->dev.kobj,
+			if ((err = sysfs_create_group(&pdev->dev.kobj,
 					&vt8231_group_temps[i])))
 				goto exit_remove_files;
 		}
@@ -756,13 +720,13 @@ int vt8231_detect(struct i2c_adapter *adapter)
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++) {
 		if (ISVOLT(i, data->uch_config)) {
-			if ((err = sysfs_create_group(&client->dev.kobj,
+			if ((err = sysfs_create_group(&pdev->dev.kobj,
 					&vt8231_group_volts[i])))
 				goto exit_remove_files;
 		}
 	}
 
-	data->class_dev = hwmon_device_register(&client->dev);
+	data->class_dev = hwmon_device_register(&pdev->dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
 		goto exit_remove_files;
@@ -771,56 +735,52 @@ int vt8231_detect(struct i2c_adapter *adapter)
 
 exit_remove_files:
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
-		sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]);
+		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]);
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
-		sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]);
+		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]);
+
+	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
 
-	sysfs_remove_group(&client->dev.kobj, &vt8231_group);
-exit_detach:
-	i2c_detach_client(client);
 exit_free:
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
+
 exit_release:
-	release_region(isa_address, VT8231_EXTENT);
+	release_region(res->start, VT8231_EXTENT);
 	return err;
 }
 
-static int vt8231_detach_client(struct i2c_client *client)
+static int __devexit vt8231_remove(struct platform_device *pdev)
 {
-	struct vt8231_data *data = i2c_get_clientdata(client);
-	int err, i;
+	struct vt8231_data *data = platform_get_drvdata(pdev);
+	int i;
 
 	hwmon_device_unregister(data->class_dev);
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_volts); i++)
-		sysfs_remove_group(&client->dev.kobj, &vt8231_group_volts[i]);
+		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_volts[i]);
 
 	for (i = 0; i < ARRAY_SIZE(vt8231_group_temps); i++)
-		sysfs_remove_group(&client->dev.kobj, &vt8231_group_temps[i]);
+		sysfs_remove_group(&pdev->dev.kobj, &vt8231_group_temps[i]);
 
-	sysfs_remove_group(&client->dev.kobj, &vt8231_group);
+	sysfs_remove_group(&pdev->dev.kobj, &vt8231_group);
 
-	if ((err = i2c_detach_client(client))) {
-		return err;
-	}
-
-	release_region(client->addr, VT8231_EXTENT);
+	release_region(data->addr, VT8231_EXTENT);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
-
 	return 0;
 }
 
-static void vt8231_init_client(struct i2c_client *client)
+static void vt8231_init_device(struct vt8231_data *data)
 {
-	vt8231_write_value(client, VT8231_REG_TEMP1_CONFIG, 0);
-	vt8231_write_value(client, VT8231_REG_TEMP2_CONFIG, 0);
+	vt8231_write_value(data, VT8231_REG_TEMP1_CONFIG, 0);
+	vt8231_write_value(data, VT8231_REG_TEMP2_CONFIG, 0);
 }
 
 static struct vt8231_data *vt8231_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct vt8231_data *data = i2c_get_clientdata(client);
+	struct vt8231_data *data = dev_get_drvdata(dev);
 	int i;
 	u16 low;
 
@@ -830,41 +790,41 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
 	    || !data->valid) {
 		for (i = 0; i < 6; i++) {
 			if (ISVOLT(i, data->uch_config)) {
-				data->in[i] = vt8231_read_value(client,
+				data->in[i] = vt8231_read_value(data,
 						regvolt[i]);
-				data->in_min[i] = vt8231_read_value(client,
+				data->in_min[i] = vt8231_read_value(data,
 						regvoltmin[i]);
-				data->in_max[i] = vt8231_read_value(client,
+				data->in_max[i] = vt8231_read_value(data,
 						regvoltmax[i]);
 			}
 		}
 		for (i = 0; i < 2; i++) {
-			data->fan[i] = vt8231_read_value(client,
+			data->fan[i] = vt8231_read_value(data,
 						VT8231_REG_FAN(i));
-			data->fan_min[i] = vt8231_read_value(client,
+			data->fan_min[i] = vt8231_read_value(data,
 						VT8231_REG_FAN_MIN(i));
 		}
 
-		low = vt8231_read_value(client, VT8231_REG_TEMP_LOW01);
+		low = vt8231_read_value(data, VT8231_REG_TEMP_LOW01);
 		low = (low >> 6) | ((low & 0x30) >> 2)
-		    | (vt8231_read_value(client, VT8231_REG_TEMP_LOW25) << 4);
+		    | (vt8231_read_value(data, VT8231_REG_TEMP_LOW25) << 4);
 		for (i = 0; i < 6; i++) {
 			if (ISTEMP(i, data->uch_config)) {
-				data->temp[i] = (vt8231_read_value(client,
+				data->temp[i] = (vt8231_read_value(data,
 						       regtemp[i]) << 2)
 						| ((low >> (2 * i)) & 0x03);
-				data->temp_max[i] = vt8231_read_value(client,
+				data->temp_max[i] = vt8231_read_value(data,
 						      regtempmax[i]);
-				data->temp_min[i] = vt8231_read_value(client,
+				data->temp_min[i] = vt8231_read_value(data,
 						      regtempmin[i]);
 			}
 		}
 
-		i = vt8231_read_value(client, VT8231_REG_FANDIV);
+		i = vt8231_read_value(data, VT8231_REG_FANDIV);
 		data->fan_div[0] = (i >> 4) & 0x03;
 		data->fan_div[1] = i >> 6;
-		data->alarms = vt8231_read_value(client, VT8231_REG_ALARM1) |
-			(vt8231_read_value(client, VT8231_REG_ALARM2) << 8);
+		data->alarms = vt8231_read_value(data, VT8231_REG_ALARM1) |
+			(vt8231_read_value(data, VT8231_REG_ALARM2) << 8);
 
 		/* Set alarm flags correctly */
 		if (!data->fan[0] && data->fan_min[0]) {
@@ -888,33 +848,102 @@ static struct vt8231_data *vt8231_update_device(struct device *dev)
 	return data;
 }
 
+static int __devinit vt8231_device_add(unsigned short address)
+{
+	struct resource res = {
+		.start	= address,
+		.end	= address + VT8231_EXTENT - 1,
+		.name	= "vt8231",
+		.flags	= IORESOURCE_IO,
+	};
+	int err;
+
+	pdev = platform_device_alloc("vt8231", address);
+	if (!pdev) {
+		err = -ENOMEM;
+		printk(KERN_ERR "vt8231: Device allocation failed\n");
+		goto exit;
+	}
+
+	err = platform_device_add_resources(pdev, &res, 1);
+	if (err) {
+		printk(KERN_ERR "vt8231: Device resource addition failed "
+		       "(%d)\n", err);
+		goto exit_device_put;
+	}
+
+	err = platform_device_add(pdev);
+	if (err) {
+		printk(KERN_ERR "vt8231: Device addition failed (%d)\n",
+		       err);
+		goto exit_device_put;
+	}
+
+	return 0;
+
+exit_device_put:
+	platform_device_put(pdev);
+exit:
+	return err;
+}
+
 static int __devinit vt8231_pci_probe(struct pci_dev *dev,
 				const struct pci_device_id *id)
 {
-	u16 val;
+	u16 address, val;
+	if (force_addr) {
+		address = force_addr & 0xff00;
+		dev_warn(&dev->dev, "Forcing ISA address 0x%x\n",
+			 address);
+
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(dev, VT8231_BASE_REG, address | 1))
+			return -ENODEV;
+	}
 
 	if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_BASE_REG,
 							&val))
 		return -ENODEV;
 
-	isa_address = val & ~(VT8231_EXTENT - 1);
-	if (isa_address == 0 && force_addr == 0) {
+	address = val & ~(VT8231_EXTENT - 1);
+	if (address == 0) {
 		dev_err(&dev->dev, "base address not set -\
 				 upgrade BIOS or use force_addr=0xaddr\n");
 		return -ENODEV;
 	}
 
-	s_bridge = pci_dev_get(dev);
+	if (PCIBIOS_SUCCESSFUL != pci_read_config_word(dev, VT8231_ENABLE_REG,
+							&val))
+		return -ENODEV;
 
-	if (i2c_isa_add_driver(&vt8231_driver)) {
-		pci_dev_put(s_bridge);
-		s_bridge = NULL;
+	if (!(val & 0x0001)) {
+		dev_warn(&dev->dev, "enabling sensors\n");
+		if (PCIBIOS_SUCCESSFUL !=
+			pci_write_config_word(dev, VT8231_ENABLE_REG,
+							val | 0x0001))
+			return -ENODEV;
 	}
 
+	if (platform_driver_register(&vt8231_driver))
+		goto exit;
+
+	/* Sets global pdev as a side effect */
+	if (vt8231_device_add(address))
+		goto exit_unregister;
+
 	/* Always return failure here.  This is to allow other drivers to bind
 	 * to this pci device.  We don't really want to have control over the
 	 * pci device, we only wanted to read as few register values from it.
 	 */
+
+	/* We do, however, mark ourselves as using the PCI device to stop it
+	   getting unloaded. */
+	s_bridge = pci_dev_get(dev);
+	return -ENODEV;
+
+exit_unregister:
+	platform_driver_unregister(&vt8231_driver);
+exit:
 	return -ENODEV;
 }
 
@@ -927,7 +956,8 @@ static void __exit sm_vt8231_exit(void)
 {
 	pci_unregister_driver(&vt8231_pci_driver);
 	if (s_bridge != NULL) {
-		i2c_isa_del_driver(&vt8231_driver);
+		platform_device_unregister(pdev);
+		platform_driver_unregister(&vt8231_driver);
 		pci_dev_put(s_bridge);
 		s_bridge = NULL;
 	}
diff --git a/drivers/hwmon/w83627ehf.c b/drivers/hwmon/w83627ehf.c
index 30a76404f0af..d9a9ec7dd84a 100644
--- a/drivers/hwmon/w83627ehf.c
+++ b/drivers/hwmon/w83627ehf.c
@@ -41,41 +41,39 @@
 #include <linux/module.h>
 #include <linux/init.h>
 #include <linux/slab.h>
-#include <linux/i2c.h>
-#include <linux/i2c-isa.h>
+#include <linux/jiffies.h>
+#include <linux/platform_device.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
+#include <linux/hwmon-vid.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <asm/io.h>
 #include "lm75.h"
 
-/* The actual ISA address is read from Super-I/O configuration space */
-static unsigned short address;
+enum kinds { w83627ehf, w83627dhg };
 
-/*
- * Super-I/O constants and functions
- */
+/* used to set data->name = w83627ehf_device_names[data->sio_kind] */
+static const char * w83627ehf_device_names[] = {
+	"w83627ehf",
+	"w83627dhg",
+};
+
+#define DRVNAME "w83627ehf"
 
 /*
- * The three following globals are initialized in w83627ehf_find(), before
- * the i2c-isa device is created. Otherwise, they could be stored in
- * w83627ehf_data. This is ugly, but necessary, and when the driver is next
- * updated to become a platform driver, the globals will disappear.
+ * Super-I/O constants and functions
  */
-static int REG;		/* The register to read/write */
-static int VAL;		/* The value to read/write */
-/* The w83627ehf/ehg have 10 voltage inputs, but the w83627dhg has 9. This
- * value is also used in w83627ehf_detect() to export a device name in sysfs
- * (e.g. w83627ehf or w83627dhg) */
-static int w83627ehf_num_in;
 
 #define W83627EHF_LD_HWM	0x0b
 
 #define SIO_REG_LDSEL		0x07	/* Logical device select */
 #define SIO_REG_DEVID		0x20	/* Device ID (2 bytes) */
+#define SIO_REG_EN_VRM10	0x2C	/* GPIO3, GPIO4 selection */
 #define SIO_REG_ENABLE		0x30	/* Logical device enable */
 #define SIO_REG_ADDR		0x60	/* Logical device address (2 bytes) */
+#define SIO_REG_VID_CTRL	0xF0	/* VID control */
+#define SIO_REG_VID_DATA	0xF1	/* VID data */
 
 #define SIO_W83627EHF_ID	0x8850
 #define SIO_W83627EHG_ID	0x8860
@@ -83,38 +81,38 @@ static int w83627ehf_num_in;
 #define SIO_ID_MASK		0xFFF0
 
 static inline void
-superio_outb(int reg, int val)
+superio_outb(int ioreg, int reg, int val)
 {
-	outb(reg, REG);
-	outb(val, VAL);
+	outb(reg, ioreg);
+	outb(val, ioreg + 1);
 }
 
 static inline int
-superio_inb(int reg)
+superio_inb(int ioreg, int reg)
 {
-	outb(reg, REG);
-	return inb(VAL);
+	outb(reg, ioreg);
+	return inb(ioreg + 1);
 }
 
 static inline void
-superio_select(int ld)
+superio_select(int ioreg, int ld)
 {
-	outb(SIO_REG_LDSEL, REG);
-	outb(ld, VAL);
+	outb(SIO_REG_LDSEL, ioreg);
+	outb(ld, ioreg + 1);
 }
 
 static inline void
-superio_enter(void)
+superio_enter(int ioreg)
 {
-	outb(0x87, REG);
-	outb(0x87, REG);
+	outb(0x87, ioreg);
+	outb(0x87, ioreg);
 }
 
 static inline void
-superio_exit(void)
+superio_exit(int ioreg)
 {
-	outb(0x02, REG);
-	outb(0x02, VAL);
+	outb(0x02, ioreg);
+	outb(0x02, ioreg + 1);
 }
 
 /*
@@ -124,8 +122,8 @@ superio_exit(void)
 #define IOREGION_ALIGNMENT	~7
 #define IOREGION_OFFSET		5
 #define IOREGION_LENGTH		2
-#define ADDR_REG_OFFSET		5
-#define DATA_REG_OFFSET		6
+#define ADDR_REG_OFFSET		0
+#define DATA_REG_OFFSET		1
 
 #define W83627EHF_REG_BANK		0x4E
 #define W83627EHF_REG_CONFIG		0x40
@@ -255,7 +253,9 @@ static inline u8 in_to_reg(u32 val, u8 nr)
  */
 
 struct w83627ehf_data {
-	struct i2c_client client;
+	int addr;	/* IO base of hw monitor block */
+	const char *name;
+
 	struct class_device *class_dev;
 	struct mutex lock;
 
@@ -264,6 +264,7 @@ struct w83627ehf_data {
 	unsigned long last_updated;	/* In jiffies */
 
 	/* Register values */
+	u8 in_num;		/* number of in inputs we have */
 	u8 in[10];		/* Register value */
 	u8 in_max[10];		/* Register value */
 	u8 in_min[10];		/* Register value */
@@ -271,6 +272,7 @@ struct w83627ehf_data {
 	u8 fan_min[5];
 	u8 fan_div[5];
 	u8 has_fan;		/* some fan inputs can be disabled */
+	u8 temp_type[3];
 	s8 temp1;
 	s8 temp1_max;
 	s8 temp1_max_hyst;
@@ -288,6 +290,14 @@ struct w83627ehf_data {
 
 	u8 fan_min_output[4]; /* minimum fan speed */
 	u8 fan_stop_time[4];
+
+	u8 vid;
+	u8 vrm;
+};
+
+struct w83627ehf_sio_data {
+	int sioreg;
+	enum kinds kind;
 };
 
 static inline int is_word_sized(u16 reg)
@@ -299,160 +309,161 @@ static inline int is_word_sized(u16 reg)
 	      || (reg & 0x00ff) == 0x55));
 }
 
-/* We assume that the default bank is 0, thus the following two functions do
-   nothing for registers which live in bank 0. For others, they respectively
-   set the bank register to the correct value (before the register is
-   accessed), and back to 0 (afterwards). */
-static inline void w83627ehf_set_bank(struct i2c_client *client, u16 reg)
+/* Registers 0x50-0x5f are banked */
+static inline void w83627ehf_set_bank(struct w83627ehf_data *data, u16 reg)
 {
-	if (reg & 0xff00) {
-		outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
-		outb_p(reg >> 8, client->addr + DATA_REG_OFFSET);
+	if ((reg & 0x00f0) == 0x50) {
+		outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
+		outb_p(reg >> 8, data->addr + DATA_REG_OFFSET);
 	}
 }
 
-static inline void w83627ehf_reset_bank(struct i2c_client *client, u16 reg)
+/* Not strictly necessary, but play it safe for now */
+static inline void w83627ehf_reset_bank(struct w83627ehf_data *data, u16 reg)
 {
 	if (reg & 0xff00) {
-		outb_p(W83627EHF_REG_BANK, client->addr + ADDR_REG_OFFSET);
-		outb_p(0, client->addr + DATA_REG_OFFSET);
+		outb_p(W83627EHF_REG_BANK, data->addr + ADDR_REG_OFFSET);
+		outb_p(0, data->addr + DATA_REG_OFFSET);
 	}
 }
 
-static u16 w83627ehf_read_value(struct i2c_client *client, u16 reg)
+static u16 w83627ehf_read_value(struct w83627ehf_data *data, u16 reg)
 {
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
 	int res, word_sized = is_word_sized(reg);
 
 	mutex_lock(&data->lock);
 
-	w83627ehf_set_bank(client, reg);
-	outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
-	res = inb_p(client->addr + DATA_REG_OFFSET);
+	w83627ehf_set_bank(data, reg);
+	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
+	res = inb_p(data->addr + DATA_REG_OFFSET);
 	if (word_sized) {
 		outb_p((reg & 0xff) + 1,
-		       client->addr + ADDR_REG_OFFSET);
-		res = (res << 8) + inb_p(client->addr + DATA_REG_OFFSET);
+		       data->addr + ADDR_REG_OFFSET);
+		res = (res << 8) + inb_p(data->addr + DATA_REG_OFFSET);
 	}
-	w83627ehf_reset_bank(client, reg);
+	w83627ehf_reset_bank(data, reg);
 
 	mutex_unlock(&data->lock);
 
 	return res;
 }
 
-static int w83627ehf_write_value(struct i2c_client *client, u16 reg, u16 value)
+static int w83627ehf_write_value(struct w83627ehf_data *data, u16 reg, u16 value)
 {
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
 	int word_sized = is_word_sized(reg);
 
 	mutex_lock(&data->lock);
 
-	w83627ehf_set_bank(client, reg);
-	outb_p(reg & 0xff, client->addr + ADDR_REG_OFFSET);
+	w83627ehf_set_bank(data, reg);
+	outb_p(reg & 0xff, data->addr + ADDR_REG_OFFSET);
 	if (word_sized) {
-		outb_p(value >> 8, client->addr + DATA_REG_OFFSET);
+		outb_p(value >> 8, data->addr + DATA_REG_OFFSET);
 		outb_p((reg & 0xff) + 1,
-		       client->addr + ADDR_REG_OFFSET);
+		       data->addr + ADDR_REG_OFFSET);
 	}
-	outb_p(value & 0xff, client->addr + DATA_REG_OFFSET);
-	w83627ehf_reset_bank(client, reg);
+	outb_p(value & 0xff, data->addr + DATA_REG_OFFSET);
+	w83627ehf_reset_bank(data, reg);
 
 	mutex_unlock(&data->lock);
 	return 0;
 }
 
 /* This function assumes that the caller holds data->update_lock */
-static void w83627ehf_write_fan_div(struct i2c_client *client, int nr)
+static void w83627ehf_write_fan_div(struct w83627ehf_data *data, int nr)
 {
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
 	u8 reg;
 
 	switch (nr) {
 	case 0:
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0xcf)
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0xcf)
 		    | ((data->fan_div[0] & 0x03) << 4);
 		/* fan5 input control bit is write only, compute the value */
 		reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
-		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xdf)
+		w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg);
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xdf)
 		    | ((data->fan_div[0] & 0x04) << 3);
-		w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+		w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);
 		break;
 	case 1:
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV1) & 0x3f)
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV1) & 0x3f)
 		    | ((data->fan_div[1] & 0x03) << 6);
 		/* fan5 input control bit is write only, compute the value */
 		reg |= (data->has_fan & (1 << 4)) ? 1 : 0;
-		w83627ehf_write_value(client, W83627EHF_REG_FANDIV1, reg);
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0xbf)
+		w83627ehf_write_value(data, W83627EHF_REG_FANDIV1, reg);
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0xbf)
 		    | ((data->fan_div[1] & 0x04) << 4);
-		w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+		w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);
 		break;
 	case 2:
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_FANDIV2) & 0x3f)
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_FANDIV2) & 0x3f)
 		    | ((data->fan_div[2] & 0x03) << 6);
-		w83627ehf_write_value(client, W83627EHF_REG_FANDIV2, reg);
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_VBAT) & 0x7f)
+		w83627ehf_write_value(data, W83627EHF_REG_FANDIV2, reg);
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_VBAT) & 0x7f)
 		    | ((data->fan_div[2] & 0x04) << 5);
-		w83627ehf_write_value(client, W83627EHF_REG_VBAT, reg);
+		w83627ehf_write_value(data, W83627EHF_REG_VBAT, reg);
 		break;
 	case 3:
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0xfc)
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0xfc)
 		    | (data->fan_div[3] & 0x03);
-		w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT) & 0x7f)
+		w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg);
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT) & 0x7f)
 		    | ((data->fan_div[3] & 0x04) << 5);
-		w83627ehf_write_value(client, W83627EHF_REG_SMI_OVT, reg);
+		w83627ehf_write_value(data, W83627EHF_REG_SMI_OVT, reg);
 		break;
 	case 4:
-		reg = (w83627ehf_read_value(client, W83627EHF_REG_DIODE) & 0x73)
+		reg = (w83627ehf_read_value(data, W83627EHF_REG_DIODE) & 0x73)
 		    | ((data->fan_div[4] & 0x03) << 2)
 		    | ((data->fan_div[4] & 0x04) << 5);
-		w83627ehf_write_value(client, W83627EHF_REG_DIODE, reg);
+		w83627ehf_write_value(data, W83627EHF_REG_DIODE, reg);
 		break;
 	}
 }
 
+static void w83627ehf_update_fan_div(struct w83627ehf_data *data)
+{
+	int i;
+
+	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
+	data->fan_div[0] = (i >> 4) & 0x03;
+	data->fan_div[1] = (i >> 6) & 0x03;
+	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV2);
+	data->fan_div[2] = (i >> 6) & 0x03;
+	i = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
+	data->fan_div[0] |= (i >> 3) & 0x04;
+	data->fan_div[1] |= (i >> 4) & 0x04;
+	data->fan_div[2] |= (i >> 5) & 0x04;
+	if (data->has_fan & ((1 << 3) | (1 << 4))) {
+		i = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
+		data->fan_div[3] = i & 0x03;
+		data->fan_div[4] = ((i >> 2) & 0x03)
+				 | ((i >> 5) & 0x04);
+	}
+	if (data->has_fan & (1 << 3)) {
+		i = w83627ehf_read_value(data, W83627EHF_REG_SMI_OVT);
+		data->fan_div[3] |= (i >> 5) & 0x04;
+	}
+}
+
 static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	int pwmcfg = 0, tolerance = 0; /* shut up the compiler */
 	int i;
 
 	mutex_lock(&data->update_lock);
 
-	if (time_after(jiffies, data->last_updated + HZ)
+	if (time_after(jiffies, data->last_updated + HZ + HZ/2)
 	 || !data->valid) {
 		/* Fan clock dividers */
-		i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
-		data->fan_div[0] = (i >> 4) & 0x03;
-		data->fan_div[1] = (i >> 6) & 0x03;
-		i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV2);
-		data->fan_div[2] = (i >> 6) & 0x03;
-		i = w83627ehf_read_value(client, W83627EHF_REG_VBAT);
-		data->fan_div[0] |= (i >> 3) & 0x04;
-		data->fan_div[1] |= (i >> 4) & 0x04;
-		data->fan_div[2] |= (i >> 5) & 0x04;
-		if (data->has_fan & ((1 << 3) | (1 << 4))) {
-			i = w83627ehf_read_value(client, W83627EHF_REG_DIODE);
-			data->fan_div[3] = i & 0x03;
-			data->fan_div[4] = ((i >> 2) & 0x03)
-					 | ((i >> 5) & 0x04);
-		}
-		if (data->has_fan & (1 << 3)) {
-			i = w83627ehf_read_value(client, W83627EHF_REG_SMI_OVT);
-			data->fan_div[3] |= (i >> 5) & 0x04;
-		}
+		w83627ehf_update_fan_div(data);
 
 		/* Measured voltages and limits */
-		for (i = 0; i < w83627ehf_num_in; i++) {
-			data->in[i] = w83627ehf_read_value(client,
+		for (i = 0; i < data->in_num; i++) {
+			data->in[i] = w83627ehf_read_value(data,
 				      W83627EHF_REG_IN(i));
-			data->in_min[i] = w83627ehf_read_value(client,
+			data->in_min[i] = w83627ehf_read_value(data,
 					  W83627EHF_REG_IN_MIN(i));
-			data->in_max[i] = w83627ehf_read_value(client,
+			data->in_max[i] = w83627ehf_read_value(data,
 					  W83627EHF_REG_IN_MAX(i));
 		}
 
@@ -461,9 +472,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 			if (!(data->has_fan & (1 << i)))
 				continue;
 
-			data->fan[i] = w83627ehf_read_value(client,
+			data->fan[i] = w83627ehf_read_value(data,
 				       W83627EHF_REG_FAN[i]);
-			data->fan_min[i] = w83627ehf_read_value(client,
+			data->fan_min[i] = w83627ehf_read_value(data,
 					   W83627EHF_REG_FAN_MIN[i]);
 
 			/* If we failed to measure the fan speed and clock
@@ -471,16 +482,16 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 			   time */
 			if (data->fan[i] == 0xff
 			 && data->fan_div[i] < 0x07) {
-			 	dev_dbg(&client->dev, "Increasing fan%d "
+			 	dev_dbg(dev, "Increasing fan%d "
 					"clock divider from %u to %u\n",
 					i + 1, div_from_reg(data->fan_div[i]),
 					div_from_reg(data->fan_div[i] + 1));
 				data->fan_div[i]++;
-				w83627ehf_write_fan_div(client, i);
+				w83627ehf_write_fan_div(data, i);
 				/* Preserve min limit if possible */
 				if (data->fan_min[i] >= 2
 				 && data->fan_min[i] != 255)
-					w83627ehf_write_value(client,
+					w83627ehf_write_value(data,
 						W83627EHF_REG_FAN_MIN[i],
 						(data->fan_min[i] /= 2));
 			}
@@ -489,9 +500,9 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 		for (i = 0; i < 4; i++) {
 			/* pwmcfg, tolarance mapped for i=0, i=1 to same reg */
 			if (i != 1) {
-				pwmcfg = w83627ehf_read_value(client,
+				pwmcfg = w83627ehf_read_value(data,
 						W83627EHF_REG_PWM_ENABLE[i]);
-				tolerance = w83627ehf_read_value(client,
+				tolerance = w83627ehf_read_value(data,
 						W83627EHF_REG_TOLERANCE[i]);
 			}
 			data->pwm_mode[i] =
@@ -500,14 +511,14 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 			data->pwm_enable[i] =
 					((pwmcfg >> W83627EHF_PWM_ENABLE_SHIFT[i])
 						& 3) + 1;
-			data->pwm[i] = w83627ehf_read_value(client,
+			data->pwm[i] = w83627ehf_read_value(data,
 						W83627EHF_REG_PWM[i]);
-			data->fan_min_output[i] = w83627ehf_read_value(client,
+			data->fan_min_output[i] = w83627ehf_read_value(data,
 						W83627EHF_REG_FAN_MIN_OUTPUT[i]);
-			data->fan_stop_time[i] = w83627ehf_read_value(client,
+			data->fan_stop_time[i] = w83627ehf_read_value(data,
 						W83627EHF_REG_FAN_STOP_TIME[i]);
 			data->target_temp[i] =
-				w83627ehf_read_value(client,
+				w83627ehf_read_value(data,
 					W83627EHF_REG_TARGET[i]) &
 					(data->pwm_mode[i] == 1 ? 0x7f : 0xff);
 			data->tolerance[i] = (tolerance >> (i == 1 ? 4 : 0))
@@ -515,26 +526,26 @@ static struct w83627ehf_data *w83627ehf_update_device(struct device *dev)
 		}
 
 		/* Measured temperatures and limits */
-		data->temp1 = w83627ehf_read_value(client,
+		data->temp1 = w83627ehf_read_value(data,
 			      W83627EHF_REG_TEMP1);
-		data->temp1_max = w83627ehf_read_value(client,
+		data->temp1_max = w83627ehf_read_value(data,
 				  W83627EHF_REG_TEMP1_OVER);
-		data->temp1_max_hyst = w83627ehf_read_value(client,
+		data->temp1_max_hyst = w83627ehf_read_value(data,
 				       W83627EHF_REG_TEMP1_HYST);
 		for (i = 0; i < 2; i++) {
-			data->temp[i] = w83627ehf_read_value(client,
+			data->temp[i] = w83627ehf_read_value(data,
 					W83627EHF_REG_TEMP[i]);
-			data->temp_max[i] = w83627ehf_read_value(client,
+			data->temp_max[i] = w83627ehf_read_value(data,
 					    W83627EHF_REG_TEMP_OVER[i]);
-			data->temp_max_hyst[i] = w83627ehf_read_value(client,
+			data->temp_max_hyst[i] = w83627ehf_read_value(data,
 						 W83627EHF_REG_TEMP_HYST[i]);
 		}
 
-		data->alarms = w83627ehf_read_value(client,
+		data->alarms = w83627ehf_read_value(data,
 					W83627EHF_REG_ALARM1) |
-			       (w83627ehf_read_value(client,
+			       (w83627ehf_read_value(data,
 					W83627EHF_REG_ALARM2) << 8) |
-			       (w83627ehf_read_value(client,
+			       (w83627ehf_read_value(data,
 					W83627EHF_REG_ALARM3) << 16);
 
 		data->last_updated = jiffies;
@@ -567,15 +578,14 @@ static ssize_t \
 store_in_##reg (struct device *dev, struct device_attribute *attr, \
 			const char *buf, size_t count) \
 { \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct w83627ehf_data *data = dev_get_drvdata(dev); \
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	u32 val = simple_strtoul(buf, NULL, 10); \
  \
 	mutex_lock(&data->update_lock); \
 	data->in_##reg[nr] = in_to_reg(val, nr); \
-	w83627ehf_write_value(client, W83627EHF_REG_IN_##REG(nr), \
+	w83627ehf_write_value(data, W83627EHF_REG_IN_##REG(nr), \
 			      data->in_##reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
@@ -673,8 +683,7 @@ static ssize_t
 store_fan_min(struct device *dev, struct device_attribute *attr,
 	      const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	unsigned int val = simple_strtoul(buf, NULL, 10);
@@ -716,18 +725,25 @@ store_fan_min(struct device *dev, struct device_attribute *attr,
 	/* Write both the fan clock divider (if it changed) and the new
 	   fan min (unconditionally) */
 	if (new_div != data->fan_div[nr]) {
-		if (new_div > data->fan_div[nr])
-			data->fan[nr] >>= (data->fan_div[nr] - new_div);
-		else
-			data->fan[nr] <<= (new_div - data->fan_div[nr]);
+		/* Preserve the fan speed reading */
+		if (data->fan[nr] != 0xff) {
+			if (new_div > data->fan_div[nr])
+				data->fan[nr] >>= new_div - data->fan_div[nr];
+			else if (data->fan[nr] & 0x80)
+				data->fan[nr] = 0xff;
+			else
+				data->fan[nr] <<= data->fan_div[nr] - new_div;
+		}
 
 		dev_dbg(dev, "fan%u clock divider changed from %u to %u\n",
 			nr + 1, div_from_reg(data->fan_div[nr]),
 			div_from_reg(new_div));
 		data->fan_div[nr] = new_div;
-		w83627ehf_write_fan_div(client, nr);
+		w83627ehf_write_fan_div(data, nr);
+		/* Give the chip time to sample a new speed value */
+		data->last_updated = jiffies;
 	}
-	w83627ehf_write_value(client, W83627EHF_REG_FAN_MIN[nr],
+	w83627ehf_write_value(data, W83627EHF_REG_FAN_MIN[nr],
 			      data->fan_min[nr]);
 	mutex_unlock(&data->update_lock);
 
@@ -788,13 +804,12 @@ static ssize_t \
 store_temp1_##reg(struct device *dev, struct device_attribute *attr, \
 		  const char *buf, size_t count) \
 { \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct w83627ehf_data *data = dev_get_drvdata(dev); \
 	u32 val = simple_strtoul(buf, NULL, 10); \
  \
 	mutex_lock(&data->update_lock); \
 	data->temp1_##reg = temp1_to_reg(val, -128000, 127000); \
-	w83627ehf_write_value(client, W83627EHF_REG_TEMP1_##REG, \
+	w83627ehf_write_value(data, W83627EHF_REG_TEMP1_##REG, \
 			      data->temp1_##reg); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
@@ -822,15 +837,14 @@ static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 	    const char *buf, size_t count) \
 { \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct w83627ehf_data *data = dev_get_drvdata(dev); \
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	u32 val = simple_strtoul(buf, NULL, 10); \
  \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = LM75_TEMP_TO_REG(val); \
-	w83627ehf_write_value(client, W83627EHF_REG_TEMP_##REG[nr], \
+	w83627ehf_write_value(data, W83627EHF_REG_TEMP_##REG[nr], \
 			      data->reg[nr]); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
@@ -838,6 +852,15 @@ store_##reg(struct device *dev, struct device_attribute *attr, \
 store_temp_reg(OVER, temp_max);
 store_temp_reg(HYST, temp_max_hyst);
 
+static ssize_t
+show_temp_type(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = w83627ehf_update_device(dev);
+	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
+	int nr = sensor_attr->index;
+	return sprintf(buf, "%d\n", (int)data->temp_type[nr]);
+}
+
 static struct sensor_device_attribute sda_temp[] = {
 	SENSOR_ATTR(temp1_input, S_IRUGO, show_temp1, NULL, 0),
 	SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 0),
@@ -857,6 +880,9 @@ static struct sensor_device_attribute sda_temp[] = {
 	SENSOR_ATTR(temp1_alarm, S_IRUGO, show_alarm, NULL, 4),
 	SENSOR_ATTR(temp2_alarm, S_IRUGO, show_alarm, NULL, 5),
 	SENSOR_ATTR(temp3_alarm, S_IRUGO, show_alarm, NULL, 13),
+	SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
+	SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
+	SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
 };
 
 #define show_pwm_reg(reg) \
@@ -877,8 +903,7 @@ static ssize_t
 store_pwm_mode(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u32 val = simple_strtoul(buf, NULL, 10);
@@ -887,12 +912,12 @@ store_pwm_mode(struct device *dev, struct device_attribute *attr,
 	if (val > 1)
 		return -EINVAL;
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
+	reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
 	data->pwm_mode[nr] = val;
 	reg &= ~(1 << W83627EHF_PWM_MODE_SHIFT[nr]);
 	if (!val)
 		reg |= 1 << W83627EHF_PWM_MODE_SHIFT[nr];
-	w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -901,15 +926,14 @@ static ssize_t
 store_pwm(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 0, 255);
 
 	mutex_lock(&data->update_lock);
 	data->pwm[nr] = val;
-	w83627ehf_write_value(client, W83627EHF_REG_PWM[nr], val);
+	w83627ehf_write_value(data, W83627EHF_REG_PWM[nr], val);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -918,8 +942,7 @@ static ssize_t
 store_pwm_enable(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u32 val = simple_strtoul(buf, NULL, 10);
@@ -928,11 +951,11 @@ store_pwm_enable(struct device *dev, struct device_attribute *attr,
 	if (!val || (val > 2))	/* only modes 1 and 2 are supported */
 		return -EINVAL;
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(client, W83627EHF_REG_PWM_ENABLE[nr]);
+	reg = w83627ehf_read_value(data, W83627EHF_REG_PWM_ENABLE[nr]);
 	data->pwm_enable[nr] = val;
 	reg &= ~(0x03 << W83627EHF_PWM_ENABLE_SHIFT[nr]);
 	reg |= (val - 1) << W83627EHF_PWM_ENABLE_SHIFT[nr];
-	w83627ehf_write_value(client, W83627EHF_REG_PWM_ENABLE[nr], reg);
+	w83627ehf_write_value(data, W83627EHF_REG_PWM_ENABLE[nr], reg);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -955,15 +978,14 @@ static ssize_t
 store_target_temp(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 127000);
 
 	mutex_lock(&data->update_lock);
 	data->target_temp[nr] = val;
-	w83627ehf_write_value(client, W83627EHF_REG_TARGET[nr], val);
+	w83627ehf_write_value(data, W83627EHF_REG_TARGET[nr], val);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -972,8 +994,7 @@ static ssize_t
 store_tolerance(struct device *dev, struct device_attribute *attr,
 			const char *buf, size_t count)
 {
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr);
 	int nr = sensor_attr->index;
 	u16 reg;
@@ -981,13 +1002,13 @@ store_tolerance(struct device *dev, struct device_attribute *attr,
 	u8 val = temp1_to_reg(simple_strtoul(buf, NULL, 10), 0, 15000);
 
 	mutex_lock(&data->update_lock);
-	reg = w83627ehf_read_value(client, W83627EHF_REG_TOLERANCE[nr]);
+	reg = w83627ehf_read_value(data, W83627EHF_REG_TOLERANCE[nr]);
 	data->tolerance[nr] = val;
 	if (nr == 1)
 		reg = (reg & 0x0f) | (val << 4);
 	else
 		reg = (reg & 0xf0) | val;
-	w83627ehf_write_value(client, W83627EHF_REG_TOLERANCE[nr], reg);
+	w83627ehf_write_value(data, W83627EHF_REG_TOLERANCE[nr], reg);
 	mutex_unlock(&data->update_lock);
 	return count;
 }
@@ -1058,14 +1079,13 @@ static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 			    const char *buf, size_t count) \
 {\
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct w83627ehf_data *data = dev_get_drvdata(dev); \
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	u32 val = SENSORS_LIMIT(simple_strtoul(buf, NULL, 10), 1, 255); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
-	w83627ehf_write_value(client, W83627EHF_REG_##REG[nr],  val); \
+	w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 }
@@ -1087,21 +1107,28 @@ static ssize_t \
 store_##reg(struct device *dev, struct device_attribute *attr, \
 			const char *buf, size_t count) \
 { \
-	struct i2c_client *client = to_i2c_client(dev); \
-	struct w83627ehf_data *data = i2c_get_clientdata(client); \
+	struct w83627ehf_data *data = dev_get_drvdata(dev); \
 	struct sensor_device_attribute *sensor_attr = to_sensor_dev_attr(attr); \
 	int nr = sensor_attr->index; \
 	u8 val = step_time_to_reg(simple_strtoul(buf, NULL, 10), \
 					data->pwm_mode[nr]); \
 	mutex_lock(&data->update_lock); \
 	data->reg[nr] = val; \
-	w83627ehf_write_value(client, W83627EHF_REG_##REG[nr], val); \
+	w83627ehf_write_value(data, W83627EHF_REG_##REG[nr], val); \
 	mutex_unlock(&data->update_lock); \
 	return count; \
 } \
 
 fan_time_functions(fan_stop_time, FAN_STOP_TIME)
 
+static ssize_t show_name(struct device *dev, struct device_attribute *attr,
+			 char *buf)
+{
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
+
+	return sprintf(buf, "%s\n", data->name);
+}
+static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
 
 static struct sensor_device_attribute sda_sf3_arrays_fan4[] = {
 	SENSOR_ATTR(pwm4_stop_time, S_IWUSR | S_IRUGO, show_fan_stop_time,
@@ -1125,8 +1152,16 @@ static struct sensor_device_attribute sda_sf3_arrays[] = {
 		    store_fan_min_output, 2),
 };
 
+static ssize_t
+show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+{
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
+	return sprintf(buf, "%d\n", vid_from_reg(data->vid, data->vrm));
+}
+static DEVICE_ATTR(cpu0_vid, S_IRUGO, show_vid, NULL);
+
 /*
- * Driver and client management
+ * Driver and device management
  */
 
 static void w83627ehf_device_remove_files(struct device *dev)
@@ -1134,12 +1169,13 @@ static void w83627ehf_device_remove_files(struct device *dev)
 	/* some entries in the following arrays may not have been used in
 	 * device_create_file(), but device_remove_file() will ignore them */
 	int i;
+	struct w83627ehf_data *data = dev_get_drvdata(dev);
 
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
 		device_remove_file(dev, &sda_sf3_arrays[i].dev_attr);
 	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays_fan4); i++)
 		device_remove_file(dev, &sda_sf3_arrays_fan4[i].dev_attr);
-	for (i = 0; i < w83627ehf_num_in; i++) {
+	for (i = 0; i < data->in_num; i++) {
 		device_remove_file(dev, &sda_in_input[i].dev_attr);
 		device_remove_file(dev, &sda_in_alarm[i].dev_attr);
 		device_remove_file(dev, &sda_in_min[i].dev_attr);
@@ -1160,43 +1196,64 @@ static void w83627ehf_device_remove_files(struct device *dev)
 	}
 	for (i = 0; i < ARRAY_SIZE(sda_temp); i++)
 		device_remove_file(dev, &sda_temp[i].dev_attr);
-}
 
-static struct i2c_driver w83627ehf_driver;
+	device_remove_file(dev, &dev_attr_name);
+	if (data->vid != 0x3f)
+		device_remove_file(dev, &dev_attr_cpu0_vid);
+}
 
-static void w83627ehf_init_client(struct i2c_client *client)
+/* Get the monitoring functions started */
+static inline void __devinit w83627ehf_init_device(struct w83627ehf_data *data)
 {
 	int i;
-	u8 tmp;
+	u8 tmp, diode;
 
 	/* Start monitoring is needed */
-	tmp = w83627ehf_read_value(client, W83627EHF_REG_CONFIG);
+	tmp = w83627ehf_read_value(data, W83627EHF_REG_CONFIG);
 	if (!(tmp & 0x01))
-		w83627ehf_write_value(client, W83627EHF_REG_CONFIG,
+		w83627ehf_write_value(data, W83627EHF_REG_CONFIG,
 				      tmp | 0x01);
 
 	/* Enable temp2 and temp3 if needed */
 	for (i = 0; i < 2; i++) {
-		tmp = w83627ehf_read_value(client,
+		tmp = w83627ehf_read_value(data,
 					   W83627EHF_REG_TEMP_CONFIG[i]);
 		if (tmp & 0x01)
-			w83627ehf_write_value(client,
+			w83627ehf_write_value(data,
 					      W83627EHF_REG_TEMP_CONFIG[i],
 					      tmp & 0xfe);
 	}
+
+	/* Enable VBAT monitoring if needed */
+	tmp = w83627ehf_read_value(data, W83627EHF_REG_VBAT);
+	if (!(tmp & 0x01))
+		w83627ehf_write_value(data, W83627EHF_REG_VBAT, tmp | 0x01);
+
+	/* Get thermal sensor types */
+	diode = w83627ehf_read_value(data, W83627EHF_REG_DIODE);
+	for (i = 0; i < 3; i++) {
+		if ((tmp & (0x02 << i)))
+			data->temp_type[i] = (diode & (0x10 << i)) ? 1 : 2;
+		else
+			data->temp_type[i] = 4; /* thermistor */
+	}
 }
 
-static int w83627ehf_detect(struct i2c_adapter *adapter)
+static int __devinit w83627ehf_probe(struct platform_device *pdev)
 {
-	struct i2c_client *client;
+	struct device *dev = &pdev->dev;
+	struct w83627ehf_sio_data *sio_data = dev->platform_data;
 	struct w83627ehf_data *data;
-	struct device *dev;
-	u8 fan4pin, fan5pin;
+	struct resource *res;
+	u8 fan4pin, fan5pin, en_vrm10;
 	int i, err = 0;
 
-	if (!request_region(address + IOREGION_OFFSET, IOREGION_LENGTH,
-	                    w83627ehf_driver.driver.name)) {
+	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
+	if (!request_region(res->start, IOREGION_LENGTH, DRVNAME)) {
 		err = -EBUSY;
+		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
+			(unsigned long)res->start,
+			(unsigned long)res->start + IOREGION_LENGTH - 1);
 		goto exit;
 	}
 
@@ -1205,41 +1262,47 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 		goto exit_release;
 	}
 
-	client = &data->client;
-	i2c_set_clientdata(client, data);
-	client->addr = address;
+	data->addr = res->start;
 	mutex_init(&data->lock);
-	client->adapter = adapter;
-	client->driver = &w83627ehf_driver;
-	client->flags = 0;
-	dev = &client->dev;
-
-	if (w83627ehf_num_in == 9)
-		strlcpy(client->name, "w83627dhg", I2C_NAME_SIZE);
-	else	/* just say ehf. 627EHG is 627EHF in lead-free packaging. */
-		strlcpy(client->name, "w83627ehf", I2C_NAME_SIZE);
-
-	data->valid = 0;
 	mutex_init(&data->update_lock);
+	data->name = w83627ehf_device_names[sio_data->kind];
+	platform_set_drvdata(pdev, data);
 
-	/* Tell the i2c layer a new client has arrived */
-	if ((err = i2c_attach_client(client)))
-		goto exit_free;
+	/* 627EHG and 627EHF have 10 voltage inputs; DHG has 9 */
+	data->in_num = (sio_data->kind == w83627dhg) ? 9 : 10;
 
 	/* Initialize the chip */
-	w83627ehf_init_client(client);
-
-	/* A few vars need to be filled upon startup */
-	for (i = 0; i < 5; i++)
-		data->fan_min[i] = w83627ehf_read_value(client,
-				   W83627EHF_REG_FAN_MIN[i]);
+	w83627ehf_init_device(data);
+
+	data->vrm = vid_which_vrm();
+	superio_enter(sio_data->sioreg);
+	/* Set VID input sensibility if needed. In theory the BIOS should
+	   have set it, but in practice it's not always the case. */
+	en_vrm10 = superio_inb(sio_data->sioreg, SIO_REG_EN_VRM10);
+	if ((en_vrm10 & 0x08) && data->vrm != 100) {
+		dev_warn(dev, "Setting VID input voltage to TTL\n");
+		superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
+			     en_vrm10 & ~0x08);
+	} else if (!(en_vrm10 & 0x08) && data->vrm == 100) {
+		dev_warn(dev, "Setting VID input voltage to VRM10\n");
+		superio_outb(sio_data->sioreg, SIO_REG_EN_VRM10,
+			     en_vrm10 | 0x08);
+	}
+	/* Read VID value */
+	superio_select(sio_data->sioreg, W83627EHF_LD_HWM);
+	if (superio_inb(sio_data->sioreg, SIO_REG_VID_CTRL) & 0x80)
+		data->vid = superio_inb(sio_data->sioreg, SIO_REG_VID_DATA) & 0x3f;
+	else {
+		dev_info(dev, "VID pins in output mode, CPU VID not "
+			 "available\n");
+		data->vid = 0x3f;
+	}
 
 	/* fan4 and fan5 share some pins with the GPIO and serial flash */
 
-	superio_enter();
-	fan5pin = superio_inb(0x24) & 0x2;
-	fan4pin = superio_inb(0x29) & 0x6;
-	superio_exit();
+	fan5pin = superio_inb(sio_data->sioreg, 0x24) & 0x2;
+	fan4pin = superio_inb(sio_data->sioreg, 0x29) & 0x6;
+	superio_exit(sio_data->sioreg);
 
 	/* It looks like fan4 and fan5 pins can be alternatively used
 	   as fan on/off switches, but fan5 control is write only :/
@@ -1248,12 +1311,15 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 	   is not the default. */
 
 	data->has_fan = 0x07; /* fan1, fan2 and fan3 */
-	i = w83627ehf_read_value(client, W83627EHF_REG_FANDIV1);
+	i = w83627ehf_read_value(data, W83627EHF_REG_FANDIV1);
 	if ((i & (1 << 2)) && (!fan4pin))
 		data->has_fan |= (1 << 3);
 	if (!(i & (1 << 1)) && (!fan5pin))
 		data->has_fan |= (1 << 4);
 
+	/* Read fan clock dividers immediately */
+	w83627ehf_update_fan_div(data);
+
 	/* Register sysfs hooks */
   	for (i = 0; i < ARRAY_SIZE(sda_sf3_arrays); i++)
 		if ((err = device_create_file(dev,
@@ -1268,7 +1334,7 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 				goto exit_remove;
 		}
 
-	for (i = 0; i < w83627ehf_num_in; i++)
+	for (i = 0; i < data->in_num; i++)
 		if ((err = device_create_file(dev, &sda_in_input[i].dev_attr))
 			|| (err = device_create_file(dev,
 				&sda_in_alarm[i].dev_attr))
@@ -1308,6 +1374,16 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 		if ((err = device_create_file(dev, &sda_temp[i].dev_attr)))
 			goto exit_remove;
 
+	err = device_create_file(dev, &dev_attr_name);
+	if (err)
+		goto exit_remove;
+
+	if (data->vid != 0x3f) {
+		err = device_create_file(dev, &dev_attr_cpu0_vid);
+		if (err)
+			goto exit_remove;
+	}
+
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
@@ -1318,95 +1394,172 @@ static int w83627ehf_detect(struct i2c_adapter *adapter)
 
 exit_remove:
 	w83627ehf_device_remove_files(dev);
-	i2c_detach_client(client);
-exit_free:
 	kfree(data);
+	platform_set_drvdata(pdev, NULL);
 exit_release:
-	release_region(address + IOREGION_OFFSET, IOREGION_LENGTH);
+	release_region(res->start, IOREGION_LENGTH);
 exit:
 	return err;
 }
 
-static int w83627ehf_detach_client(struct i2c_client *client)
+static int __devexit w83627ehf_remove(struct platform_device *pdev)
 {
-	struct w83627ehf_data *data = i2c_get_clientdata(client);
-	int err;
+	struct w83627ehf_data *data = platform_get_drvdata(pdev);
 
 	hwmon_device_unregister(data->class_dev);
-	w83627ehf_device_remove_files(&client->dev);
-
-	if ((err = i2c_detach_client(client)))
-		return err;
-	release_region(client->addr + IOREGION_OFFSET, IOREGION_LENGTH);
+	w83627ehf_device_remove_files(&pdev->dev);
+	release_region(data->addr, IOREGION_LENGTH);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	return 0;
 }
 
-static struct i2c_driver w83627ehf_driver = {
+static struct platform_driver w83627ehf_driver = {
 	.driver = {
 		.owner	= THIS_MODULE,
-		.name	= "w83627ehf",
+		.name	= DRVNAME,
 	},
-	.attach_adapter	= w83627ehf_detect,
-	.detach_client	= w83627ehf_detach_client,
+	.probe		= w83627ehf_probe,
+	.remove		= __devexit_p(w83627ehf_remove),
 };
 
-static int __init w83627ehf_find(int sioaddr, unsigned short *addr)
+/* w83627ehf_find() looks for a '627 in the Super-I/O config space */
+static int __init w83627ehf_find(int sioaddr, unsigned short *addr,
+				 struct w83627ehf_sio_data *sio_data)
 {
+	static const char __initdata sio_name_W83627EHF[] = "W83627EHF";
+	static const char __initdata sio_name_W83627EHG[] = "W83627EHG";
+	static const char __initdata sio_name_W83627DHG[] = "W83627DHG";
+
 	u16 val;
+	const char *sio_name;
 
-	REG = sioaddr;
-	VAL = sioaddr + 1;
-	superio_enter();
+	superio_enter(sioaddr);
 
-	val = (superio_inb(SIO_REG_DEVID) << 8)
-	    | superio_inb(SIO_REG_DEVID + 1);
+	val = (superio_inb(sioaddr, SIO_REG_DEVID) << 8)
+	    | superio_inb(sioaddr, SIO_REG_DEVID + 1);
 	switch (val & SIO_ID_MASK) {
-	case SIO_W83627DHG_ID:
-		w83627ehf_num_in = 9;
-		break;
 	case SIO_W83627EHF_ID:
+		sio_data->kind = w83627ehf;
+		sio_name = sio_name_W83627EHF;
+		break;
 	case SIO_W83627EHG_ID:
-		w83627ehf_num_in = 10;
+		sio_data->kind = w83627ehf;
+		sio_name = sio_name_W83627EHG;
+		break;
+	case SIO_W83627DHG_ID:
+		sio_data->kind = w83627dhg;
+		sio_name = sio_name_W83627DHG;
 		break;
 	default:
-		printk(KERN_WARNING "w83627ehf: unsupported chip ID: 0x%04x\n",
-			val);
-		superio_exit();
+		if (val != 0xffff)
+			pr_debug(DRVNAME ": unsupported chip ID: 0x%04x\n",
+				 val);
+		superio_exit(sioaddr);
 		return -ENODEV;
 	}
 
-	superio_select(W83627EHF_LD_HWM);
-	val = (superio_inb(SIO_REG_ADDR) << 8)
-	    | superio_inb(SIO_REG_ADDR + 1);
+	/* We have a known chip, find the HWM I/O address */
+	superio_select(sioaddr, W83627EHF_LD_HWM);
+	val = (superio_inb(sioaddr, SIO_REG_ADDR) << 8)
+	    | superio_inb(sioaddr, SIO_REG_ADDR + 1);
 	*addr = val & IOREGION_ALIGNMENT;
 	if (*addr == 0) {
-		superio_exit();
+		printk(KERN_ERR DRVNAME ": Refusing to enable a Super-I/O "
+		       "device with a base I/O port 0.\n");
+		superio_exit(sioaddr);
 		return -ENODEV;
 	}
 
 	/* Activate logical device if needed */
-	val = superio_inb(SIO_REG_ENABLE);
-	if (!(val & 0x01))
-		superio_outb(SIO_REG_ENABLE, val | 0x01);
+	val = superio_inb(sioaddr, SIO_REG_ENABLE);
+	if (!(val & 0x01)) {
+		printk(KERN_WARNING DRVNAME ": Forcibly enabling Super-I/O. "
+		       "Sensor is probably unusable.\n");
+		superio_outb(sioaddr, SIO_REG_ENABLE, val | 0x01);
+	}
+
+	superio_exit(sioaddr);
+	pr_info(DRVNAME ": Found %s chip at %#x\n", sio_name, *addr);
+	sio_data->sioreg = sioaddr;
 
-	superio_exit();
 	return 0;
 }
 
+/* when Super-I/O functions move to a separate file, the Super-I/O
+ * bus will manage the lifetime of the device and this module will only keep
+ * track of the w83627ehf driver. But since we platform_device_alloc(), we
+ * must keep track of the device */
+static struct platform_device *pdev;
+
 static int __init sensors_w83627ehf_init(void)
 {
-	if (w83627ehf_find(0x2e, &address)
-	 && w83627ehf_find(0x4e, &address))
+	int err;
+	unsigned short address;
+	struct resource res;
+	struct w83627ehf_sio_data sio_data;
+
+	/* initialize sio_data->kind and sio_data->sioreg.
+	 *
+	 * when Super-I/O functions move to a separate file, the Super-I/O
+	 * driver will probe 0x2e and 0x4e and auto-detect the presence of a
+	 * w83627ehf hardware monitor, and call probe() */
+	if (w83627ehf_find(0x2e, &address, &sio_data) &&
+	    w83627ehf_find(0x4e, &address, &sio_data))
 		return -ENODEV;
 
-	return i2c_isa_add_driver(&w83627ehf_driver);
+	err = platform_driver_register(&w83627ehf_driver);
+	if (err)
+		goto exit;
+
+	if (!(pdev = platform_device_alloc(DRVNAME, address))) {
+		err = -ENOMEM;
+		printk(KERN_ERR DRVNAME ": Device allocation failed\n");
+		goto exit_unregister;
+	}
+
+	err = platform_device_add_data(pdev, &sio_data,
+				       sizeof(struct w83627ehf_sio_data));
+	if (err) {
+		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
+		goto exit_device_put;
+	}
+
+	memset(&res, 0, sizeof(res));
+	res.name = DRVNAME;
+	res.start = address + IOREGION_OFFSET;
+	res.end = address + IOREGION_OFFSET + IOREGION_LENGTH - 1;
+	res.flags = IORESOURCE_IO;
+	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;
+	}
+
+	/* platform_device_add calls probe() */
+	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_unregister:
+	platform_driver_unregister(&w83627ehf_driver);
+exit:
+	return err;
 }
 
 static void __exit sensors_w83627ehf_exit(void)
 {
-	i2c_isa_del_driver(&w83627ehf_driver);
+	platform_device_unregister(pdev);
+	platform_driver_unregister(&w83627ehf_driver);
 }
 
 MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
diff --git a/drivers/hwmon/w83627hf.c b/drivers/hwmon/w83627hf.c
index 12cb40a975de..7a4a15f4bf8b 100644
--- a/drivers/hwmon/w83627hf.c
+++ b/drivers/hwmon/w83627hf.c
@@ -220,6 +220,18 @@ static const u8 regpwm[] = { W83627THF_REG_PWM1, W83627THF_REG_PWM2,
 #define W836X7HF_REG_PWM(type, nr) (((type) == w83627hf) ? \
                                      regpwm_627hf[(nr) - 1] : regpwm[(nr) - 1])
 
+#define W83627HF_REG_PWM_FREQ		0x5C	/* Only for the 627HF */
+
+#define W83637HF_REG_PWM_FREQ1		0x00	/* 697HF/687THF too */
+#define W83637HF_REG_PWM_FREQ2		0x02	/* 697HF/687THF too */
+#define W83637HF_REG_PWM_FREQ3		0x10	/* 687THF too */
+
+static const u8 W83637HF_REG_PWM_FREQ[] = { W83637HF_REG_PWM_FREQ1,
+					W83637HF_REG_PWM_FREQ2,
+					W83637HF_REG_PWM_FREQ3 };
+
+#define W83627HF_BASE_PWM_FREQ	46870
+
 #define W83781D_REG_I2C_ADDR 0x48
 #define W83781D_REG_I2C_SUBADDR 0x4A
 
@@ -267,6 +279,49 @@ static int TEMP_FROM_REG(u8 reg)
 
 #define PWM_TO_REG(val) (SENSORS_LIMIT((val),0,255))
 
+static inline unsigned long pwm_freq_from_reg_627hf(u8 reg)
+{
+	unsigned long freq;
+	freq = W83627HF_BASE_PWM_FREQ >> reg;
+	return freq;
+}
+static inline u8 pwm_freq_to_reg_627hf(unsigned long val)
+{
+	u8 i;
+	/* Only 5 dividers (1 2 4 8 16)
+	   Search for the nearest available frequency */
+	for (i = 0; i < 4; i++) {
+		if (val > (((W83627HF_BASE_PWM_FREQ >> i) +
+			    (W83627HF_BASE_PWM_FREQ >> (i+1))) / 2))
+			break;
+	}
+	return i;
+}
+
+static inline unsigned long pwm_freq_from_reg(u8 reg)
+{
+	/* Clock bit 8 -> 180 kHz or 24 MHz */
+	unsigned long clock = (reg & 0x80) ? 180000UL : 24000000UL;
+
+	reg &= 0x7f;
+	/* This should not happen but anyway... */
+	if (reg == 0)
+		reg++;
+	return (clock / (reg << 8));
+}
+static inline u8 pwm_freq_to_reg(unsigned long val)
+{
+	/* Minimum divider value is 0x01 and maximum is 0x7F */
+	if (val >= 93750)	/* The highest we can do */
+		return 0x01;
+	if (val >= 720)	/* Use 24 MHz clock */
+		return (24000000UL / (val << 8));
+	if (val < 6)		/* The lowest we can do */
+		return 0xFF;
+	else			/* Use 180 kHz clock */
+		return (0x80 | (180000UL / (val << 8)));
+}
+
 #define BEEP_MASK_FROM_REG(val)		 (val)
 #define BEEP_MASK_TO_REG(val)		((val) & 0xffffff)
 #define BEEP_ENABLE_TO_REG(val)		((val)?1:0)
@@ -316,6 +371,7 @@ struct w83627hf_data {
 	u32 beep_mask;		/* Register encoding, combined */
 	u8 beep_enable;		/* Boolean */
 	u8 pwm[3];		/* Register value */
+	u8 pwm_freq[3];		/* Register value */
 	u16 sens[3];		/* 782D/783S only.
 				   1 = pentium diode; 2 = 3904 diode;
 				   3000-5000 = thermistor beta.
@@ -331,7 +387,7 @@ struct w83627hf_sio_data {
 
 
 static int w83627hf_probe(struct platform_device *pdev);
-static int w83627hf_remove(struct platform_device *pdev);
+static int __devexit w83627hf_remove(struct platform_device *pdev);
 
 static int w83627hf_read_value(struct w83627hf_data *data, u16 reg);
 static int w83627hf_write_value(struct w83627hf_data *data, u16 reg, u16 value);
@@ -852,6 +908,64 @@ sysfs_pwm(2);
 sysfs_pwm(3);
 
 static ssize_t
+show_pwm_freq_reg(struct device *dev, char *buf, int nr)
+{
+	struct w83627hf_data *data = w83627hf_update_device(dev);
+	if (data->type == w83627hf)
+		return sprintf(buf, "%ld\n",
+			pwm_freq_from_reg_627hf(data->pwm_freq[nr - 1]));
+	else
+		return sprintf(buf, "%ld\n",
+			pwm_freq_from_reg(data->pwm_freq[nr - 1]));
+}
+
+static ssize_t
+store_pwm_freq_reg(struct device *dev, const char *buf, size_t count, int nr)
+{
+	struct w83627hf_data *data = dev_get_drvdata(dev);
+	static const u8 mask[]={0xF8, 0x8F};
+	u32 val;
+
+	val = simple_strtoul(buf, NULL, 10);
+
+	mutex_lock(&data->update_lock);
+
+	if (data->type == w83627hf) {
+		data->pwm_freq[nr - 1] = pwm_freq_to_reg_627hf(val);
+		w83627hf_write_value(data, W83627HF_REG_PWM_FREQ,
+				(data->pwm_freq[nr - 1] << ((nr - 1)*4)) |
+				(w83627hf_read_value(data,
+				W83627HF_REG_PWM_FREQ) & mask[nr - 1]));
+	} else {
+		data->pwm_freq[nr - 1] = pwm_freq_to_reg(val);
+		w83627hf_write_value(data, W83637HF_REG_PWM_FREQ[nr - 1],
+				data->pwm_freq[nr - 1]);
+	}
+
+	mutex_unlock(&data->update_lock);
+	return count;
+}
+
+#define sysfs_pwm_freq(offset) \
+static ssize_t show_regs_pwm_freq_##offset(struct device *dev, \
+		struct device_attribute *attr, char *buf) \
+{ \
+	return show_pwm_freq_reg(dev, buf, offset); \
+} \
+static ssize_t \
+store_regs_pwm_freq_##offset(struct device *dev, \
+		struct device_attribute *attr, const char *buf, size_t count) \
+{ \
+	return store_pwm_freq_reg(dev, buf, count, offset); \
+} \
+static DEVICE_ATTR(pwm##offset##_freq, S_IRUGO | S_IWUSR, \
+		  show_regs_pwm_freq_##offset, store_regs_pwm_freq_##offset);
+
+sysfs_pwm_freq(1);
+sysfs_pwm_freq(2);
+sysfs_pwm_freq(3);
+
+static ssize_t
 show_sensor_reg(struct device *dev, char *buf, int nr)
 {
 	struct w83627hf_data *data = w83627hf_update_device(dev);
@@ -1077,6 +1191,9 @@ static struct attribute *w83627hf_attributes_opt[] = {
 
 	&dev_attr_pwm3.attr,
 
+	&dev_attr_pwm1_freq.attr,
+	&dev_attr_pwm2_freq.attr,
+	&dev_attr_pwm3_freq.attr,
 	NULL
 };
 
@@ -1139,7 +1256,9 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 		 || (err = device_create_file(dev, &dev_attr_in5_max))
 		 || (err = device_create_file(dev, &dev_attr_in6_input))
 		 || (err = device_create_file(dev, &dev_attr_in6_min))
-		 || (err = device_create_file(dev, &dev_attr_in6_max)))
+		 || (err = device_create_file(dev, &dev_attr_in6_max))
+		 || (err = device_create_file(dev, &dev_attr_pwm1_freq))
+		 || (err = device_create_file(dev, &dev_attr_pwm2_freq)))
 			goto ERROR4;
 
 	if (data->type != w83697hf)
@@ -1169,6 +1288,12 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 		if ((err = device_create_file(dev, &dev_attr_pwm3)))
 			goto ERROR4;
 
+	if (data->type == w83637hf || data->type == w83687thf)
+		if ((err = device_create_file(dev, &dev_attr_pwm1_freq))
+		 || (err = device_create_file(dev, &dev_attr_pwm2_freq))
+		 || (err = device_create_file(dev, &dev_attr_pwm3_freq)))
+			goto ERROR4;
+
 	data->class_dev = hwmon_device_register(dev);
 	if (IS_ERR(data->class_dev)) {
 		err = PTR_ERR(data->class_dev);
@@ -1181,6 +1306,7 @@ static int __devinit w83627hf_probe(struct platform_device *pdev)
 	sysfs_remove_group(&dev->kobj, &w83627hf_group);
 	sysfs_remove_group(&dev->kobj, &w83627hf_group_opt);
       ERROR3:
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
       ERROR1:
 	release_region(res->start, WINB_REGION_SIZE);
@@ -1193,11 +1319,11 @@ static int __devexit w83627hf_remove(struct platform_device *pdev)
 	struct w83627hf_data *data = platform_get_drvdata(pdev);
 	struct resource *res;
 
-	platform_set_drvdata(pdev, NULL);
 	hwmon_device_unregister(data->class_dev);
 
 	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group);
 	sysfs_remove_group(&pdev->dev.kobj, &w83627hf_group_opt);
+	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
@@ -1472,6 +1598,20 @@ static struct w83627hf_data *w83627hf_update_device(struct device *dev)
 			   (data->type == w83627hf || data->type == w83697hf))
 				break;
 		}
+		if (data->type == w83627hf) {
+				u8 tmp = w83627hf_read_value(data,
+						W83627HF_REG_PWM_FREQ);
+				data->pwm_freq[0] = tmp & 0x07;
+				data->pwm_freq[1] = (tmp >> 4) & 0x07;
+		} else if (data->type != w83627thf) {
+			for (i = 1; i <= 3; i++) {
+				data->pwm_freq[i - 1] =
+					w83627hf_read_value(data,
+						W83637HF_REG_PWM_FREQ[i - 1]);
+				if (i == 2 && (data->type == w83697hf))
+					break;
+			}
+		}
 
 		data->temp = w83627hf_read_value(data, W83781D_REG_TEMP(1));
 		data->temp_max =
@@ -1548,15 +1688,12 @@ static int __init w83627hf_device_add(unsigned short address,
 		goto exit_device_put;
 	}
 
-	pdev->dev.platform_data = kmalloc(sizeof(struct w83627hf_sio_data),
-					  GFP_KERNEL);
-	if (!pdev->dev.platform_data) {
-		err = -ENOMEM;
+	err = platform_device_add_data(pdev, sio_data,
+				       sizeof(struct w83627hf_sio_data));
+	if (err) {
 		printk(KERN_ERR DRVNAME ": Platform data allocation failed\n");
 		goto exit_device_put;
 	}
-	memcpy(pdev->dev.platform_data, sio_data,
-	       sizeof(struct w83627hf_sio_data));
 
 	err = platform_device_add(pdev);
 	if (err) {
diff --git a/drivers/hwmon/w83781d.c b/drivers/hwmon/w83781d.c
index f85b48fea1c4..dcc941a5aaff 100644
--- a/drivers/hwmon/w83781d.c
+++ b/drivers/hwmon/w83781d.c
@@ -740,9 +740,9 @@ store_sensor(struct device *dev, struct device_attribute *da,
 static SENSOR_DEVICE_ATTR(temp1_type, S_IRUGO | S_IWUSR,
 	show_sensor, store_sensor, 0);
 static SENSOR_DEVICE_ATTR(temp2_type, S_IRUGO | S_IWUSR,
-	show_sensor, store_sensor, 0);
+	show_sensor, store_sensor, 1);
 static SENSOR_DEVICE_ATTR(temp3_type, S_IRUGO | S_IWUSR,
-	show_sensor, store_sensor, 0);
+	show_sensor, store_sensor, 2);
 
 /* I2C devices get this name attribute automatically, but for ISA devices
    we must create it by ourselves. */
@@ -1746,7 +1746,7 @@ w83781d_isa_device_add(unsigned short address)
 {
 	struct resource res = {
 		.start	= address,
-		.end	= address + W83781D_EXTENT,
+		.end	= address + W83781D_EXTENT - 1,
 		.name	= "w83781d",
 		.flags	= IORESOURCE_IO,
 	};