浏览代码

Merge branch 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging

* 'hwmon-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging:
  hwmon: (lm85) Don't bind to Winbond/Nuvoton WPCD377I
  hwmon: (pcf8591) Documentation clean-ups
  hwmon: Clearly mark ACPI drivers as such
  hwmon: Use resource_size
  hwmon: Include <linux/io.h> instead of <asm/io.h>
  hwmon: (tmp421) Add documentation
  hwmon: Add driver for Texas Instruments TMP421/422/423 sensor chips
  hwmon-vid: Ignore 6th VID pin of AMD family 0Fh processors
  hwmon: (asus_atk0110) Add maintainer information
  hwmon: (abituguru3) Support multiple DMI strings per chip ID
Linus Torvalds 16 年之前
父节点
当前提交
96c015b75f

+ 15 - 13
Documentation/hwmon/pcf8591

@@ -2,11 +2,11 @@ Kernel driver pcf8591
 =====================
 =====================
 
 
 Supported chips:
 Supported chips:
-  * Philips PCF8591
+  * Philips/NXP PCF8591
     Prefix: 'pcf8591'
     Prefix: 'pcf8591'
     Addresses scanned: I2C 0x48 - 0x4f
     Addresses scanned: I2C 0x48 - 0x4f
-    Datasheet: Publicly available at the Philips Semiconductor website
-               http://www.semiconductors.philips.com/pip/PCF8591P.html
+    Datasheet: Publicly available at the NXP website
+               http://www.nxp.com/pip/PCF8591_6.html
 
 
 Authors:
 Authors:
         Aurelien Jarno <aurelien@aurel32.net>
         Aurelien Jarno <aurelien@aurel32.net>
@@ -16,9 +16,10 @@ Authors:
 
 
 Description
 Description
 -----------
 -----------
+
 The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
 The PCF8591 is an 8-bit A/D and D/A converter (4 analog inputs and one
-analog output) for the I2C bus produced by Philips Semiconductors. It
-is designed to provide a byte I2C interface to up to 4 separate devices.
+analog output) for the I2C bus produced by Philips Semiconductors (now NXP).
+It is designed to provide a byte I2C interface to up to 4 separate devices.
 
 
 The PCF8591 has 4 analog inputs programmable as single-ended or
 The PCF8591 has 4 analog inputs programmable as single-ended or
 differential inputs :
 differential inputs :
@@ -58,8 +59,8 @@ Accessing PCF8591 via /sys interface
 -------------------------------------
 -------------------------------------
 
 
 ! Be careful !
 ! Be careful !
-The PCF8591 is plainly impossible to detect ! Stupid chip.
-So every chip with address in the interval [48..4f] is
+The PCF8591 is plainly impossible to detect! Stupid chip.
+So every chip with address in the interval [0x48..0x4f] is
 detected as PCF8591. If you have other chips in this address
 detected as PCF8591. If you have other chips in this address
 range, the workaround is to load this module after the one
 range, the workaround is to load this module after the one
 for your others chips.
 for your others chips.
@@ -67,19 +68,20 @@ for your others chips.
 On detection (i.e. insmod, modprobe et al.), directories are being
 On detection (i.e. insmod, modprobe et al.), directories are being
 created for each detected PCF8591:
 created for each detected PCF8591:
 
 
-/sys/bus/devices/<0>-<1>/
+/sys/bus/i2c/devices/<0>-<1>/
 where <0> is the bus the chip was detected on (e. g. i2c-0)
 where <0> is the bus the chip was detected on (e. g. i2c-0)
 and <1> the chip address ([48..4f])
 and <1> the chip address ([48..4f])
 
 
 Inside these directories, there are such files:
 Inside these directories, there are such files:
-in0, in1, in2, in3, out0_enable, out0_output, name
+in0_input, in1_input, in2_input, in3_input, out0_enable, out0_output, name
 
 
 Name contains chip name.
 Name contains chip name.
 
 
-The in0, in1, in2 and in3 files are RO. Reading gives the value of the
-corresponding channel. Depending on the current analog inputs configuration,
-files in2 and/or in3 do not exist. Values range are from 0 to 255 for single
-ended inputs and -128 to +127 for differential inputs (8-bit ADC).
+The in0_input, in1_input, in2_input and in3_input files are RO. Reading gives
+the value of the corresponding channel. Depending on the current analog inputs
+configuration, files in2_input and in3_input may not exist. Values range
+from 0 to 255 for single ended inputs and -128 to +127 for differential inputs
+(8-bit ADC).
 
 
 The out0_enable file is RW. Reading gives "1" for analog output enabled and
 The out0_enable file is RW. Reading gives "1" for analog output enabled and
 "0" for analog output disabled. Writing accepts "0" and "1" accordingly.
 "0" for analog output disabled. Writing accepts "0" and "1" accordingly.

+ 36 - 0
Documentation/hwmon/tmp421

@@ -0,0 +1,36 @@
+Kernel driver tmp421
+====================
+
+Supported chips:
+  * Texas Instruments TMP421
+    Prefix: 'tmp421'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+  * Texas Instruments TMP422
+    Prefix: 'tmp422'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+  * Texas Instruments TMP423
+    Prefix: 'tmp423'
+    Addresses scanned: I2C 0x2a, 0x4c, 0x4d, 0x4e and 0x4f
+    Datasheet: http://focus.ti.com/docs/prod/folders/print/tmp421.html
+
+Authors:
+	Andre Prendel <andre.prendel@gmx.de>
+
+Description
+-----------
+
+This driver implements support for Texas Instruments TMP421, TMP422
+and TMP423 temperature sensor chips. These chips implement one local
+and up to one (TMP421), up to two (TMP422) or up to three (TMP423)
+remote sensors. Temperature is measured in degrees Celsius. The chips
+are wired over I2C/SMBus and specified over a temperature range of -40
+to +125 degrees Celsius. Resolution for both the local and remote
+channels is 0.0625 degree C.
+
+The chips support only temperature measurement. The driver exports
+the temperature values via the following sysfs files:
+
+temp[1-4]_input
+temp[2-4]_fault

+ 6 - 0
MAINTAINERS

@@ -931,6 +931,12 @@ W:	http://wireless.kernel.org/en/users/Drivers/ar9170
 S:	Maintained
 S:	Maintained
 F:	drivers/net/wireless/ath/ar9170/
 F:	drivers/net/wireless/ath/ar9170/
 
 
+ATK0110 HWMON DRIVER
+M:	Luca Tettamanti <kronos.it@gmail.com>
+L:	lm-sensors@lm-sensors.org
+S:	Maintained
+F:	drivers/hwmon/asus_atk0110.c
+
 ATI_REMOTE2 DRIVER
 ATI_REMOTE2 DRIVER
 M:	Ville Syrjala <syrjala@sci.fi>
 M:	Ville Syrjala <syrjala@sci.fi>
 S:	Maintained
 S:	Maintained

+ 64 - 46
drivers/hwmon/Kconfig

@@ -28,6 +28,17 @@ config HWMON_VID
 	tristate
 	tristate
 	default n
 	default n
 
 
+config HWMON_DEBUG_CHIP
+	bool "Hardware Monitoring Chip debugging messages"
+	default n
+	help
+	  Say Y here if you want the I2C chip drivers to produce a bunch of
+	  debug messages to the system log.  Select this if you are having
+	  a problem with I2C support and want to see more of what is going
+	  on.
+
+comment "Native drivers"
+
 config SENSORS_ABITUGURU
 config SENSORS_ABITUGURU
 	tristate "Abit uGuru (rev 1 & 2)"
 	tristate "Abit uGuru (rev 1 & 2)"
 	depends on X86 && EXPERIMENTAL
 	depends on X86 && EXPERIMENTAL
@@ -248,18 +259,6 @@ config SENSORS_ASB100
 	  This driver can also be built as a module.  If so, the module
 	  This driver can also be built as a module.  If so, the module
 	  will be called asb100.
 	  will be called asb100.
 
 
-config SENSORS_ATK0110
-	tristate "ASUS ATK0110 ACPI hwmon"
-	depends on X86 && ACPI && EXPERIMENTAL
-	help
-	  If you say yes here you get support for the ACPI hardware
-	  monitoring interface found in many ASUS motherboards. This
-	  driver will provide readings of fans, voltages and temperatures
-	  through the system firmware.
-
-	  This driver can also be built as a module. If so, the module
-	  will be called asus_atk0110.
-
 config SENSORS_ATXP1
 config SENSORS_ATXP1
 	tristate "Attansic ATXP1 VID controller"
 	tristate "Attansic ATXP1 VID controller"
 	depends on I2C && EXPERIMENTAL
 	depends on I2C && EXPERIMENTAL
@@ -814,6 +813,16 @@ config SENSORS_TMP401
 	  This driver can also be built as a module.  If so, the module
 	  This driver can also be built as a module.  If so, the module
 	  will be called tmp401.
 	  will be called tmp401.
 
 
+config SENSORS_TMP421
+	tristate "Texas Instruments TMP421 and compatible"
+	depends on I2C && EXPERIMENTAL
+	help
+	  If you say yes here you get support for Texas Instruments TMP421,
+	  TMP422 and TMP423 temperature sensor chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called tmp421.
+
 config SENSORS_VIA686A
 config SENSORS_VIA686A
 	tristate "VIA686A"
 	tristate "VIA686A"
 	depends on PCI
 	depends on PCI
@@ -964,34 +973,6 @@ config SENSORS_HDAPS
 	  Say Y here if you have an applicable laptop and want to experience
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of hdaps.
 	  the awesome power of hdaps.
 
 
-config SENSORS_LIS3LV02D
-	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
-	depends on ACPI && INPUT
-	select INPUT_POLLDEV
-	select NEW_LEDS
-	select LEDS_CLASS
-	default n
-	help
-	  This driver provides support for the LIS3LV02Dx accelerometer. In
-	  particular, it can be found in a number of HP laptops, which have the
-	  "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such
-	  systems the driver should load automatically (via ACPI). The
-	  accelerometer might also be found in other systems, connected via SPI
-	  or I2C.  The accelerometer data is readable via
-	  /sys/devices/platform/lis3lv02d.
-
-	  This driver also provides an absolute input class device, allowing
-	  the laptop to act as a pinball machine-esque joystick. On HP laptops,
-	  if the led infrastructure is activated, support for a led indicating
-	  disk protection will be provided as hp:red:hddprotection.
-
-	  This driver can also be built as modules.  If so, the core module
-	  will be called lis3lv02d and a specific module for HP laptops will be
-	  called hp_accel.
-
-	  Say Y here if you have an applicable laptop and want to experience
-	  the awesome power of lis3lv02d.
-
 config SENSORS_LIS3_SPI
 config SENSORS_LIS3_SPI
 	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
 	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer (SPI)"
 	depends on !ACPI && SPI_MASTER && INPUT
 	depends on !ACPI && SPI_MASTER && INPUT
@@ -1034,13 +1015,50 @@ config SENSORS_APPLESMC
 	  Say Y here if you have an applicable laptop and want to experience
 	  Say Y here if you have an applicable laptop and want to experience
 	  the awesome power of applesmc.
 	  the awesome power of applesmc.
 
 
-config HWMON_DEBUG_CHIP
-	bool "Hardware Monitoring Chip debugging messages"
+if ACPI
+
+comment "ACPI drivers"
+
+config SENSORS_ATK0110
+	tristate "ASUS ATK0110"
+	depends on X86 && EXPERIMENTAL
+	help
+	  If you say yes here you get support for the ACPI hardware
+	  monitoring interface found in many ASUS motherboards. This
+	  driver will provide readings of fans, voltages and temperatures
+	  through the system firmware.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called asus_atk0110.
+
+config SENSORS_LIS3LV02D
+	tristate "STMicroeletronics LIS3LV02Dx three-axis digital accelerometer"
+	depends on INPUT
+	select INPUT_POLLDEV
+	select NEW_LEDS
+	select LEDS_CLASS
 	default n
 	default n
 	help
 	help
-	  Say Y here if you want the I2C chip drivers to produce a bunch of
-	  debug messages to the system log.  Select this if you are having
-	  a problem with I2C support and want to see more of what is going
-	  on.
+	  This driver provides support for the LIS3LV02Dx accelerometer. In
+	  particular, it can be found in a number of HP laptops, which have the
+	  "Mobile Data Protection System 3D" or "3D DriveGuard" feature. On such
+	  systems the driver should load automatically (via ACPI). The
+	  accelerometer might also be found in other systems, connected via SPI
+	  or I2C.  The accelerometer data is readable via
+	  /sys/devices/platform/lis3lv02d.
+
+	  This driver also provides an absolute input class device, allowing
+	  the laptop to act as a pinball machine-esque joystick. On HP laptops,
+	  if the led infrastructure is activated, support for a led indicating
+	  disk protection will be provided as hp:red:hddprotection.
+
+	  This driver can also be built as modules.  If so, the core module
+	  will be called lis3lv02d and a specific module for HP laptops will be
+	  called hp_accel.
+
+	  Say Y here if you have an applicable laptop and want to experience
+	  the awesome power of lis3lv02d.
+
+endif # ACPI
 
 
 endif # HWMON
 endif # HWMON

+ 5 - 2
drivers/hwmon/Makefile

@@ -5,6 +5,10 @@
 obj-$(CONFIG_HWMON)		+= hwmon.o
 obj-$(CONFIG_HWMON)		+= hwmon.o
 obj-$(CONFIG_HWMON_VID)		+= hwmon-vid.o
 obj-$(CONFIG_HWMON_VID)		+= hwmon-vid.o
 
 
+# APCI drivers
+obj-$(CONFIG_SENSORS_ATK0110)	+= asus_atk0110.o
+
+# Native drivers
 # asb100, then w83781d go first, as they can override other drivers' addresses.
 # asb100, then w83781d go first, as they can override other drivers' addresses.
 obj-$(CONFIG_SENSORS_ASB100)	+= asb100.o
 obj-$(CONFIG_SENSORS_ASB100)	+= asb100.o
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
 obj-$(CONFIG_SENSORS_W83627HF)	+= w83627hf.o
@@ -29,10 +33,8 @@ obj-$(CONFIG_SENSORS_ADT7462)	+= adt7462.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_ADT7470)	+= adt7470.o
 obj-$(CONFIG_SENSORS_ADT7473)	+= adt7473.o
 obj-$(CONFIG_SENSORS_ADT7473)	+= adt7473.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
 obj-$(CONFIG_SENSORS_ADT7475)	+= adt7475.o
-
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_APPLESMC)	+= applesmc.o
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
 obj-$(CONFIG_SENSORS_AMS)	+= ams/
-obj-$(CONFIG_SENSORS_ATK0110)	+= asus_atk0110.o
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_ATXP1)	+= atxp1.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_CORETEMP)	+= coretemp.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
 obj-$(CONFIG_SENSORS_DME1737)	+= dme1737.o
@@ -84,6 +86,7 @@ obj-$(CONFIG_SENSORS_SMSC47M1)	+= smsc47m1.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_SMSC47M192)+= smsc47m192.o
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_THMC50)	+= thmc50.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
 obj-$(CONFIG_SENSORS_TMP401)	+= tmp401.o
+obj-$(CONFIG_SENSORS_TMP421)	+= tmp421.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT1211)	+= vt1211.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o
 obj-$(CONFIG_SENSORS_VT8231)	+= vt8231.o

+ 1 - 1
drivers/hwmon/abituguru.c

@@ -32,7 +32,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/dmi.h>
 #include <linux/dmi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 /* Banks */
 /* Banks */
 #define ABIT_UGURU_ALARM_BANK			0x20 /* 1x 3 bytes */
 #define ABIT_UGURU_ALARM_BANK			0x20 /* 1x 3 bytes */

+ 41 - 38
drivers/hwmon/abituguru3.c

@@ -34,7 +34,7 @@
 #include <linux/hwmon.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/dmi.h>
 #include <linux/dmi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 /* uGuru3 bank addresses */
 /* uGuru3 bank addresses */
 #define ABIT_UGURU3_SETTINGS_BANK		0x01
 #define ABIT_UGURU3_SETTINGS_BANK		0x01
@@ -117,9 +117,12 @@ struct abituguru3_sensor_info {
 	int offset;
 	int offset;
 };
 };
 
 
+/* Avoid use of flexible array members */
+#define ABIT_UGURU3_MAX_DMI_NAMES 2
+
 struct abituguru3_motherboard_info {
 struct abituguru3_motherboard_info {
 	u16 id;
 	u16 id;
-	const char *dmi_name;
+	const char *dmi_name[ABIT_UGURU3_MAX_DMI_NAMES + 1];
 	/* + 1 -> end of sensors indicated by a sensor with name == NULL */
 	/* + 1 -> end of sensors indicated by a sensor with name == NULL */
 	struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
 	struct abituguru3_sensor_info sensors[ABIT_UGURU3_MAX_NO_SENSORS + 1];
 };
 };
@@ -164,7 +167,7 @@ struct abituguru3_data {
 
 
 /* Constants */
 /* Constants */
 static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
-	{ 0x000C, NULL /* Unknown, need DMI string */, {
+	{ 0x000C, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -186,7 +189,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
 		{ "AUX1 Fan",		35, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x000D, NULL /* Abit AW8, need DMI string */, {
+	{ 0x000D, { NULL } /* Abit AW8, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -215,7 +218,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x000E, NULL /* AL-8, need DMI string */, {
+	{ 0x000E, { NULL } /* AL-8, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -236,7 +239,8 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x000F, NULL /* Unknown, need DMI string */, {
+	{ 0x000F, { NULL } /* Unknown, need DMI string */, {
+
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -257,7 +261,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0010, NULL /* Abit NI8 SLI GR, need DMI string */, {
+	{ 0x0010, { NULL } /* Abit NI8 SLI GR, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -279,7 +283,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "OTES1 Fan",		36, 2, 60, 1, 0 },
 		{ "OTES1 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0011, "AT8 32X", {
+	{ 0x0011, { "AT8 32X", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -306,7 +310,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 Fan",		37, 2, 60, 1, 0 },
 		{ "AUX3 Fan",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0012, NULL /* Abit AN8 32X, need DMI string */, {
+	{ 0x0012, { NULL } /* Abit AN8 32X, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -328,7 +332,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX1 Fan",		36, 2, 60, 1, 0 },
 		{ "AUX1 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0013, NULL /* Abit AW8D, need DMI string */, {
+	{ 0x0013, { NULL } /* Abit AW8D, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -357,7 +361,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ "AUX5 Fan",		39, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0014, "AB9", /* + AB9 Pro */ {
+	{ 0x0014, { "AB9", "AB9 Pro", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -378,7 +382,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ "SYS Fan",		34, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0015, NULL /* Unknown, need DMI string */, {
+	{ 0x0015, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR",		 1, 0, 20, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR VTT",		 2, 0, 10, 1, 0 },
@@ -402,7 +406,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0016, "AW9D-MAX", {
+	{ 0x0016, { "AW9D-MAX", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -430,7 +434,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "OTES1 Fan",		38, 2, 60, 1, 0 },
 		{ "OTES1 Fan",		38, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0017, NULL /* Unknown, need DMI string */, {
+	{ 0x0017, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -455,7 +459,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 FAN",		37, 2, 60, 1, 0 },
 		{ "AUX3 FAN",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0018, "AB9 QuadGT", {
+	{ 0x0018, { "AB9 QuadGT", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -482,7 +486,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0019, "IN9 32X MAX", {
+	{ 0x0019, { "IN9 32X MAX", NULL }, {
 		{ "CPU Core",		 7, 0, 10, 1, 0 },
 		{ "CPU Core",		 7, 0, 10, 1, 0 },
 		{ "DDR2",		13, 0, 20, 1, 0 },
 		{ "DDR2",		13, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		14, 0, 10, 1, 0 },
 		{ "DDR2 VTT",		14, 0, 10, 1, 0 },
@@ -509,7 +513,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 FAN",		36, 2, 60, 1, 0 },
 		{ "AUX3 FAN",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x001A, "IP35 Pro", {
+	{ 0x001A, { "IP35 Pro", "IP35 Pro XE", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -537,7 +541,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX4 Fan",		37, 2, 60, 1, 0 },
 		{ "AUX4 Fan",		37, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x001B, NULL /* Unknown, need DMI string */, {
+	{ 0x001B, { NULL } /* Unknown, need DMI string */, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR3",		 1, 0, 20, 1, 0 },
 		{ "DDR3",		 1, 0, 20, 1, 0 },
 		{ "DDR3 VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR3 VTT",		 2, 0, 10, 1, 0 },
@@ -564,7 +568,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x001C, "IX38 QuadGT", {
+	{ 0x001C, { "IX38 QuadGT", NULL }, {
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "CPU Core",		 0, 0, 10, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2",		 1, 0, 20, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
 		{ "DDR2 VTT",		 2, 0, 10, 1, 0 },
@@ -591,7 +595,7 @@ static const struct abituguru3_motherboard_info abituguru3_motherboards[] = {
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ "AUX3 Fan",		36, 2, 60, 1, 0 },
 		{ NULL, 0, 0, 0, 0, 0 } }
 		{ NULL, 0, 0, 0, 0, 0 } }
 	},
 	},
-	{ 0x0000, NULL, { { NULL, 0, 0, 0, 0, 0 } } }
+	{ 0x0000, { NULL }, { { NULL, 0, 0, 0, 0, 0 } } }
 };
 };
 
 
 
 
@@ -946,15 +950,6 @@ static int __devinit abituguru3_probe(struct platform_device *pdev)
 	printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
 	printk(KERN_INFO ABIT_UGURU3_NAME ": found Abit uGuru3, motherboard "
 		"ID: %04X\n", (unsigned int)id);
 		"ID: %04X\n", (unsigned int)id);
 
 
-#ifdef CONFIG_DMI
-	if (!abituguru3_motherboards[i].dmi_name) {
-		printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
-			"not detected using DMI. Please send the output of "
-			"\"dmidecode\" to the abituguru3 maintainer "
-			"(see MAINTAINERS)\n");
-	}
-#endif
-
 	/* Fill the sysfs attr array */
 	/* Fill the sysfs attr array */
 	sysfs_attr_i = 0;
 	sysfs_attr_i = 0;
 	sysfs_filename = data->sysfs_names;
 	sysfs_filename = data->sysfs_names;
@@ -1131,6 +1126,7 @@ static int __init abituguru3_dmi_detect(void)
 {
 {
 	const char *board_vendor, *board_name;
 	const char *board_vendor, *board_name;
 	int i, err = (force) ? 1 : -ENODEV;
 	int i, err = (force) ? 1 : -ENODEV;
+	const char *const *dmi_name;
 	size_t sublen;
 	size_t sublen;
 
 
 	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
 	board_vendor = dmi_get_system_info(DMI_BOARD_VENDOR);
@@ -1151,17 +1147,17 @@ static int __init abituguru3_dmi_detect(void)
 		sublen--;
 		sublen--;
 
 
 	for (i = 0; abituguru3_motherboards[i].id; i++) {
 	for (i = 0; abituguru3_motherboards[i].id; i++) {
-		const char *dmi_name = abituguru3_motherboards[i].dmi_name;
-		if (!dmi_name || strlen(dmi_name) != sublen)
-			continue;
-		if (!strncasecmp(board_name, dmi_name, sublen))
-			break;
+		dmi_name = abituguru3_motherboards[i].dmi_name;
+		for ( ; *dmi_name; dmi_name++) {
+			if (strlen(*dmi_name) != sublen)
+				continue;
+			if (!strncasecmp(board_name, *dmi_name, sublen))
+				return 0;
+		}
 	}
 	}
 
 
-	if (!abituguru3_motherboards[i].id)
-		return 1;
-
-	return 0;
+	/* No match found */
+	return 1;
 }
 }
 
 
 #else /* !CONFIG_DMI */
 #else /* !CONFIG_DMI */
@@ -1221,6 +1217,13 @@ static int __init abituguru3_init(void)
 		err = abituguru3_detect();
 		err = abituguru3_detect();
 		if (err)
 		if (err)
 			return err;
 			return err;
+
+#ifdef CONFIG_DMI
+		printk(KERN_WARNING ABIT_UGURU3_NAME ": this motherboard was "
+			"not detected using DMI. Please send the output of "
+			"\"dmidecode\" to the abituguru3 maintainer "
+			"(see MAINTAINERS)\n");
+#endif
 	}
 	}
 
 
 	err = platform_driver_register(&abituguru3_driver);
 	err = platform_driver_register(&abituguru3_driver);

+ 1 - 1
drivers/hwmon/applesmc.c

@@ -35,7 +35,7 @@
 #include <linux/dmi.h>
 #include <linux/dmi.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include <linux/leds.h>
 #include <linux/leds.h>
 #include <linux/hwmon.h>
 #include <linux/hwmon.h>
 #include <linux/workqueue.h>
 #include <linux/workqueue.h>

+ 1 - 1
drivers/hwmon/dme1737.c

@@ -35,7 +35,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 /* ISA device, if found */
 /* ISA device, if found */
 static struct platform_device *pdev;
 static struct platform_device *pdev;

+ 1 - 1
drivers/hwmon/f71805f.c

@@ -40,7 +40,7 @@
 #include <linux/sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static unsigned short force_id;
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 module_param(force_id, ushort, 0);

+ 1 - 2
drivers/hwmon/hdaps.c

@@ -35,8 +35,7 @@
 #include <linux/timer.h>
 #include <linux/timer.h>
 #include <linux/dmi.h>
 #include <linux/dmi.h>
 #include <linux/jiffies.h>
 #include <linux/jiffies.h>
-
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 #define HDAPS_LOW_PORT		0x1600	/* first port used by hdaps */
 #define HDAPS_LOW_PORT		0x1600	/* first port used by hdaps */
 #define HDAPS_NR_PORTS		0x30	/* number of ports: 0x1600 - 0x162f */
 #define HDAPS_NR_PORTS		0x30	/* number of ports: 0x1600 - 0x162f */

+ 9 - 1
drivers/hwmon/hwmon-vid.c

@@ -179,8 +179,14 @@ struct vrm_model {
 static struct vrm_model vrm_models[] = {
 static struct vrm_model vrm_models[] = {
 	{X86_VENDOR_AMD, 0x6, ANY, ANY, 90},		/* Athlon Duron etc */
 	{X86_VENDOR_AMD, 0x6, ANY, ANY, 90},		/* Athlon Duron etc */
 	{X86_VENDOR_AMD, 0xF, 0x3F, ANY, 24},		/* Athlon 64, Opteron */
 	{X86_VENDOR_AMD, 0xF, 0x3F, ANY, 24},		/* Athlon 64, Opteron */
-	{X86_VENDOR_AMD, 0xF, ANY, ANY, 25},		/* NPT family 0Fh */
+	/* In theory, all NPT family 0Fh processors have 6 VID pins and should
+	   thus use vrm 25, however in practice not all mainboards route the
+	   6th VID pin because it is never needed. So we use the 5 VID pin
+	   variant (vrm 24) for the models which exist today. */
+	{X86_VENDOR_AMD, 0xF, 0x7F, ANY, 24},		/* NPT family 0Fh */
+	{X86_VENDOR_AMD, 0xF, ANY, ANY, 25},		/* future fam. 0Fh */
 	{X86_VENDOR_AMD, 0x10, ANY, ANY, 25},		/* NPT family 10h */
 	{X86_VENDOR_AMD, 0x10, ANY, ANY, 25},		/* NPT family 10h */
+
 	{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13},		/* Pentium M (130 nm) */
 	{X86_VENDOR_INTEL, 0x6, 0x9, ANY, 13},		/* Pentium M (130 nm) */
 	{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85},		/* Tualatin */
 	{X86_VENDOR_INTEL, 0x6, 0xB, ANY, 85},		/* Tualatin */
 	{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13},		/* Pentium M (90 nm) */
 	{X86_VENDOR_INTEL, 0x6, 0xD, ANY, 13},		/* Pentium M (90 nm) */
@@ -191,12 +197,14 @@ static struct vrm_model vrm_models[] = {
 	{X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90},		/* P4 Willamette */
 	{X86_VENDOR_INTEL, 0xF, 0x1, ANY, 90},		/* P4 Willamette */
 	{X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90},		/* P4 Northwood */
 	{X86_VENDOR_INTEL, 0xF, 0x2, ANY, 90},		/* P4 Northwood */
 	{X86_VENDOR_INTEL, 0xF, ANY, ANY, 100},		/* Prescott and above assume VRD 10 */
 	{X86_VENDOR_INTEL, 0xF, ANY, ANY, 100},		/* Prescott and above assume VRD 10 */
+
 	{X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},	/* Eden ESP/Ezra */
 	{X86_VENDOR_CENTAUR, 0x6, 0x7, ANY, 85},	/* Eden ESP/Ezra */
 	{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},	/* Ezra T */
 	{X86_VENDOR_CENTAUR, 0x6, 0x8, 0x7, 85},	/* Ezra T */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},	/* Nemiah */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, 0x7, 85},	/* Nemiah */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},	/* C3-M, Eden-N */
 	{X86_VENDOR_CENTAUR, 0x6, 0x9, ANY, 17},	/* C3-M, Eden-N */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0},		/* No information */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, 0x7, 0},		/* No information */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},	/* C7, Esther */
 	{X86_VENDOR_CENTAUR, 0x6, 0xA, ANY, 13},	/* C7, Esther */
+
 	{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}		/* stop here */
 	{X86_VENDOR_UNKNOWN, ANY, ANY, ANY, 0}		/* stop here */
 };
 };
 
 

+ 1 - 1
drivers/hwmon/it87.c

@@ -50,7 +50,7 @@
 #include <linux/string.h>
 #include <linux/string.h>
 #include <linux/dmi.h>
 #include <linux/dmi.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 #define DRVNAME "it87"
 #define DRVNAME "it87"
 
 

+ 1 - 1
drivers/hwmon/lm78.c

@@ -31,7 +31,7 @@
 #include <linux/hwmon-sysfs.h>
 #include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 /* ISA device, if found */
 /* ISA device, if found */
 static struct platform_device *pdev;
 static struct platform_device *pdev;

+ 32 - 0
drivers/hwmon/lm85.c

@@ -75,6 +75,8 @@ I2C_CLIENT_INSMOD_7(lm85b, lm85c, adm1027, adt7463, adt7468, emc6d100,
 #define	LM85_VERSTEP_GENERIC2		0x70
 #define	LM85_VERSTEP_GENERIC2		0x70
 #define	LM85_VERSTEP_LM85C		0x60
 #define	LM85_VERSTEP_LM85C		0x60
 #define	LM85_VERSTEP_LM85B		0x62
 #define	LM85_VERSTEP_LM85B		0x62
+#define	LM85_VERSTEP_LM96000_1		0x68
+#define	LM85_VERSTEP_LM96000_2		0x69
 #define	LM85_VERSTEP_ADM1027		0x60
 #define	LM85_VERSTEP_ADM1027		0x60
 #define	LM85_VERSTEP_ADT7463		0x62
 #define	LM85_VERSTEP_ADT7463		0x62
 #define	LM85_VERSTEP_ADT7463C		0x6A
 #define	LM85_VERSTEP_ADT7463C		0x6A
@@ -1133,6 +1135,26 @@ static void lm85_init_client(struct i2c_client *client)
 		dev_warn(&client->dev, "Device is not ready\n");
 		dev_warn(&client->dev, "Device is not ready\n");
 }
 }
 
 
+static int lm85_is_fake(struct i2c_client *client)
+{
+	/*
+	 * Differenciate between real LM96000 and Winbond WPCD377I. The latter
+	 * emulate the former except that it has no hardware monitoring function
+	 * so the readings are always 0.
+	 */
+	int i;
+	u8 in_temp, fan;
+
+	for (i = 0; i < 8; i++) {
+		in_temp = i2c_smbus_read_byte_data(client, 0x20 + i);
+		fan = i2c_smbus_read_byte_data(client, 0x28 + i);
+		if (in_temp != 0x00 || fan != 0xff)
+			return 0;
+	}
+
+	return 1;
+}
+
 /* Return 0 if detection is successful, -ENODEV otherwise */
 /* Return 0 if detection is successful, -ENODEV otherwise */
 static int lm85_detect(struct i2c_client *client, int kind,
 static int lm85_detect(struct i2c_client *client, int kind,
 		       struct i2c_board_info *info)
 		       struct i2c_board_info *info)
@@ -1173,6 +1195,16 @@ static int lm85_detect(struct i2c_client *client, int kind,
 			case LM85_VERSTEP_LM85B:
 			case LM85_VERSTEP_LM85B:
 				kind = lm85b;
 				kind = lm85b;
 				break;
 				break;
+			case LM85_VERSTEP_LM96000_1:
+			case LM85_VERSTEP_LM96000_2:
+				/* Check for Winbond WPCD377I */
+				if (lm85_is_fake(client)) {
+					dev_dbg(&adapter->dev,
+						"Found Winbond WPCD377I, "
+						"ignoring\n");
+					return -ENODEV;
+				}
+				break;
 			}
 			}
 		} else if (company == LM85_COMPANY_ANALOG_DEV) {
 		} else if (company == LM85_COMPANY_ANALOG_DEV) {
 			switch (verstep) {
 			switch (verstep) {

+ 1 - 1
drivers/hwmon/pc87360.c

@@ -44,7 +44,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static u8 devid;
 static u8 devid;
 static struct platform_device *pdev;
 static struct platform_device *pdev;

+ 4 - 4
drivers/hwmon/pc87427.c

@@ -33,7 +33,7 @@
 #include <linux/sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static unsigned short force_id;
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 module_param(force_id, ushort, 0);
@@ -435,7 +435,7 @@ static int __devinit pc87427_probe(struct platform_device *pdev)
 	/* This will need to be revisited when we add support for
 	/* This will need to be revisited when we add support for
 	   temperature and voltage monitoring. */
 	   temperature and voltage monitoring. */
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
+	if (!request_region(res->start, resource_size(res), DRVNAME)) {
 		err = -EBUSY;
 		err = -EBUSY;
 		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
 		dev_err(&pdev->dev, "Failed to request region 0x%lx-0x%lx\n",
 			(unsigned long)res->start, (unsigned long)res->end);
 			(unsigned long)res->start, (unsigned long)res->end);
@@ -475,7 +475,7 @@ exit_remove_files:
 		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
 		sysfs_remove_group(&pdev->dev.kobj, &pc87427_group_fan[i]);
 	}
 	}
 exit_release_region:
 exit_release_region:
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 exit_kfree:
 exit_kfree:
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 	kfree(data);
@@ -500,7 +500,7 @@ static int __devexit pc87427_remove(struct platform_device *pdev)
 	kfree(data);
 	kfree(data);
 
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 
 
 	return 0;
 	return 0;
 }
 }

+ 1 - 1
drivers/hwmon/sis5595.c

@@ -63,7 +63,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 
 
 /* If force_addr is set to anything different from 0, we forcibly enable
 /* If force_addr is set to anything different from 0, we forcibly enable

+ 1 - 1
drivers/hwmon/smsc47b397.c

@@ -37,7 +37,7 @@
 #include <linux/init.h>
 #include <linux/init.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static unsigned short force_id;
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 module_param(force_id, ushort, 0);

+ 1 - 1
drivers/hwmon/smsc47m1.c

@@ -38,7 +38,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static unsigned short force_id;
 static unsigned short force_id;
 module_param(force_id, ushort, 0);
 module_param(force_id, ushort, 0);

+ 347 - 0
drivers/hwmon/tmp421.c

@@ -0,0 +1,347 @@
+/* tmp421.c
+ *
+ * Copyright (C) 2009 Andre Prendel <andre.prendel@gmx.de>
+ * Preliminary support by:
+ * Melvin Rook, Raymond Ng
+ *
+ * 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.
+ */
+
+/*
+ * Driver for the Texas Instruments TMP421 SMBus temperature sensor IC.
+ * Supported models: TMP421, TMP422, TMP423
+ */
+
+#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/err.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { 0x2a, 0x4c, 0x4d, 0x4e, 0x4f,
+				       I2C_CLIENT_END };
+
+/* Insmod parameters */
+I2C_CLIENT_INSMOD_3(tmp421, tmp422, tmp423);
+
+/* The TMP421 registers */
+#define TMP421_CONFIG_REG_1			0x09
+#define TMP421_CONVERSION_RATE_REG		0x0B
+#define TMP421_MANUFACTURER_ID_REG		0xFE
+#define TMP421_DEVICE_ID_REG			0xFF
+
+static const u8 TMP421_TEMP_MSB[4]		= { 0x00, 0x01, 0x02, 0x03 };
+static const u8 TMP421_TEMP_LSB[4]		= { 0x10, 0x11, 0x12, 0x13 };
+
+/* Flags */
+#define TMP421_CONFIG_SHUTDOWN			0x40
+#define TMP421_CONFIG_RANGE			0x04
+
+/* Manufacturer / Device ID's */
+#define TMP421_MANUFACTURER_ID			0x55
+#define TMP421_DEVICE_ID			0x21
+#define TMP422_DEVICE_ID			0x22
+#define TMP423_DEVICE_ID			0x23
+
+static const struct i2c_device_id tmp421_id[] = {
+	{ "tmp421", tmp421 },
+	{ "tmp422", tmp422 },
+	{ "tmp423", tmp423 },
+	{ }
+};
+MODULE_DEVICE_TABLE(i2c, tmp421_id);
+
+struct tmp421_data {
+	struct device *hwmon_dev;
+	struct mutex update_lock;
+	char valid;
+	unsigned long last_updated;
+	int kind;
+	u8 config;
+	s16 temp[4];
+};
+
+static int temp_from_s16(s16 reg)
+{
+	int temp = reg;
+
+	return (temp * 1000 + 128) / 256;
+}
+
+static int temp_from_u16(u16 reg)
+{
+	int temp = reg;
+
+	/* Add offset for extended temperature range. */
+	temp -= 64 * 256;
+
+	return (temp * 1000 + 128) / 256;
+}
+
+static struct tmp421_data *tmp421_update_device(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct tmp421_data *data = i2c_get_clientdata(client);
+	int i;
+
+	mutex_lock(&data->update_lock);
+
+	if (time_after(jiffies, data->last_updated + 2 * HZ) || !data->valid) {
+		data->config = i2c_smbus_read_byte_data(client,
+			TMP421_CONFIG_REG_1);
+
+		for (i = 0; i <= data->kind; i++) {
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+				TMP421_TEMP_MSB[i]) << 8;
+			data->temp[i] |= i2c_smbus_read_byte_data(client,
+				TMP421_TEMP_LSB[i]);
+		}
+		data->last_updated = jiffies;
+		data->valid = 1;
+	}
+
+	mutex_unlock(&data->update_lock);
+
+	return data;
+}
+
+static ssize_t show_temp_value(struct device *dev,
+			       struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp421_data *data = tmp421_update_device(dev);
+	int temp;
+
+	mutex_lock(&data->update_lock);
+	if (data->config & TMP421_CONFIG_RANGE)
+		temp = temp_from_u16(data->temp[index]);
+	else
+		temp = temp_from_s16(data->temp[index]);
+	mutex_unlock(&data->update_lock);
+
+	return sprintf(buf, "%d\n", temp);
+}
+
+static ssize_t show_fault(struct device *dev,
+			  struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct tmp421_data *data = tmp421_update_device(dev);
+
+	/*
+	 * The OPEN bit signals a fault. This is bit 0 of the temperature
+	 * register (low byte).
+	 */
+	if (data->temp[index] & 0x01)
+		return sprintf(buf, "1\n");
+	else
+		return sprintf(buf, "0\n");
+}
+
+static mode_t tmp421_is_visible(struct kobject *kobj, struct attribute *a,
+				int n)
+{
+	struct device *dev = container_of(kobj, struct device, kobj);
+	struct tmp421_data *data = dev_get_drvdata(dev);
+	struct device_attribute *devattr;
+	unsigned int index;
+
+	devattr = container_of(a, struct device_attribute, attr);
+	index = to_sensor_dev_attr(devattr)->index;
+
+	if (data->kind > index)
+		return a->mode;
+
+	return 0;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_value, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp_value, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_fault, S_IRUGO, show_fault, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp3_input, S_IRUGO, show_temp_value, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp3_fault, S_IRUGO, show_fault, NULL, 2);
+static SENSOR_DEVICE_ATTR(temp4_input, S_IRUGO, show_temp_value, NULL, 3);
+static SENSOR_DEVICE_ATTR(temp4_fault, S_IRUGO, show_fault, NULL, 3);
+
+static struct attribute *tmp421_attr[] = {
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_fault.dev_attr.attr,
+	&sensor_dev_attr_temp3_input.dev_attr.attr,
+	&sensor_dev_attr_temp3_fault.dev_attr.attr,
+	&sensor_dev_attr_temp4_input.dev_attr.attr,
+	&sensor_dev_attr_temp4_fault.dev_attr.attr,
+	NULL
+};
+
+static const struct attribute_group tmp421_group = {
+	.attrs = tmp421_attr,
+	.is_visible = tmp421_is_visible,
+};
+
+static int tmp421_init_client(struct i2c_client *client)
+{
+	int config, config_orig;
+
+	/* Set the conversion rate to 2 Hz */
+	i2c_smbus_write_byte_data(client, TMP421_CONVERSION_RATE_REG, 0x05);
+
+	/* Start conversions (disable shutdown if necessary) */
+	config = i2c_smbus_read_byte_data(client, TMP421_CONFIG_REG_1);
+	if (config < 0) {
+		dev_err(&client->dev, "Could not read configuration"
+			 " register (%d)\n", config);
+		return -ENODEV;
+	}
+
+	config_orig = config;
+	config &= ~TMP421_CONFIG_SHUTDOWN;
+
+	if (config != config_orig) {
+		dev_info(&client->dev, "Enable monitoring chip\n");
+		i2c_smbus_write_byte_data(client, TMP421_CONFIG_REG_1, config);
+	}
+
+	return 0;
+}
+
+static int tmp421_detect(struct i2c_client *client, int kind,
+			 struct i2c_board_info *info)
+{
+	struct i2c_adapter *adapter = client->adapter;
+	const char *names[] = { "TMP421", "TMP422", "TMP423" };
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+		return -ENODEV;
+
+	if (kind <= 0) {
+		u8 reg;
+
+		reg = i2c_smbus_read_byte_data(client,
+					       TMP421_MANUFACTURER_ID_REG);
+		if (reg != TMP421_MANUFACTURER_ID)
+			return -ENODEV;
+
+		reg = i2c_smbus_read_byte_data(client,
+					       TMP421_DEVICE_ID_REG);
+		switch (reg) {
+		case TMP421_DEVICE_ID:
+			kind = tmp421;
+			break;
+		case TMP422_DEVICE_ID:
+			kind = tmp422;
+			break;
+		case TMP423_DEVICE_ID:
+			kind = tmp423;
+			break;
+		default:
+			return -ENODEV;
+		}
+	}
+	strlcpy(info->type, tmp421_id[kind - 1].name, I2C_NAME_SIZE);
+	dev_info(&adapter->dev, "Detected TI %s chip at 0x%02x\n",
+		 names[kind - 1], client->addr);
+
+	return 0;
+}
+
+static int tmp421_probe(struct i2c_client *client,
+			const struct i2c_device_id *id)
+{
+	struct tmp421_data *data;
+	int err;
+
+	data = kzalloc(sizeof(struct tmp421_data), GFP_KERNEL);
+	if (!data)
+		return -ENOMEM;
+
+	i2c_set_clientdata(client, data);
+	mutex_init(&data->update_lock);
+	data->kind = id->driver_data;
+
+	err = tmp421_init_client(client);
+	if (err)
+		goto exit_free;
+
+	err = sysfs_create_group(&client->dev.kobj, &tmp421_group);
+	if (err)
+		goto exit_free;
+
+	data->hwmon_dev = hwmon_device_register(&client->dev);
+	if (IS_ERR(data->hwmon_dev)) {
+		err = PTR_ERR(data->hwmon_dev);
+		data->hwmon_dev = NULL;
+		goto exit_remove;
+	}
+	return 0;
+
+exit_remove:
+	sysfs_remove_group(&client->dev.kobj, &tmp421_group);
+
+exit_free:
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+
+	return err;
+}
+
+static int tmp421_remove(struct i2c_client *client)
+{
+	struct tmp421_data *data = i2c_get_clientdata(client);
+
+	hwmon_device_unregister(data->hwmon_dev);
+	sysfs_remove_group(&client->dev.kobj, &tmp421_group);
+
+	i2c_set_clientdata(client, NULL);
+	kfree(data);
+
+	return 0;
+}
+
+static struct i2c_driver tmp421_driver = {
+	.class = I2C_CLASS_HWMON,
+	.driver = {
+		.name	= "tmp421",
+	},
+	.probe = tmp421_probe,
+	.remove = tmp421_remove,
+	.id_table = tmp421_id,
+	.detect = tmp421_detect,
+	.address_data = &addr_data,
+};
+
+static int __init tmp421_init(void)
+{
+	return i2c_add_driver(&tmp421_driver);
+}
+
+static void __exit tmp421_exit(void)
+{
+	i2c_del_driver(&tmp421_driver);
+}
+
+MODULE_AUTHOR("Andre Prendel <andre.prendel@gmx.de>");
+MODULE_DESCRIPTION("Texas Instruments TMP421/422/423 temperature sensor"
+		   " driver");
+MODULE_LICENSE("GPL");
+
+module_init(tmp421_init);
+module_exit(tmp421_exit);

+ 1 - 1
drivers/hwmon/via686a.c

@@ -42,7 +42,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/sysfs.h>
 #include <linux/sysfs.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 
 
 /* If force_addr is set to anything different from 0, we forcibly enable
 /* If force_addr is set to anything different from 0, we forcibly enable

+ 4 - 4
drivers/hwmon/vt1211.c

@@ -33,7 +33,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static int uch_config = -1;
 static int uch_config = -1;
 module_param(uch_config, int, 0);
 module_param(uch_config, int, 0);
@@ -1136,7 +1136,7 @@ static int __devinit vt1211_probe(struct platform_device *pdev)
 	}
 	}
 
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	if (!request_region(res->start, res->end - res->start + 1, DRVNAME)) {
+	if (!request_region(res->start, resource_size(res), DRVNAME)) {
 		err = -EBUSY;
 		err = -EBUSY;
 		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
 		dev_err(dev, "Failed to request region 0x%lx-0x%lx\n",
 			(unsigned long)res->start, (unsigned long)res->end);
 			(unsigned long)res->start, (unsigned long)res->end);
@@ -1209,7 +1209,7 @@ EXIT_DEV_REMOVE:
 	dev_err(dev, "Sysfs interface creation failed (%d)\n", err);
 	dev_err(dev, "Sysfs interface creation failed (%d)\n", err);
 EXIT_DEV_REMOVE_SILENT:
 EXIT_DEV_REMOVE_SILENT:
 	vt1211_remove_sysfs(pdev);
 	vt1211_remove_sysfs(pdev);
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 EXIT_KFREE:
 EXIT_KFREE:
 	platform_set_drvdata(pdev, NULL);
 	platform_set_drvdata(pdev, NULL);
 	kfree(data);
 	kfree(data);
@@ -1228,7 +1228,7 @@ static int __devexit vt1211_remove(struct platform_device *pdev)
 	kfree(data);
 	kfree(data);
 
 
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
 	res = platform_get_resource(pdev, IORESOURCE_IO, 0);
-	release_region(res->start, res->end - res->start + 1);
+	release_region(res->start, resource_size(res));
 
 
 	return 0;
 	return 0;
 }
 }

+ 1 - 1
drivers/hwmon/vt8231.c

@@ -36,7 +36,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 
 
 static int force_addr;
 static int force_addr;
 module_param(force_addr, int, 0);
 module_param(force_addr, int, 0);

+ 1 - 1
drivers/hwmon/w83627ehf.c

@@ -51,7 +51,7 @@
 #include <linux/err.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include "lm75.h"
 #include "lm75.h"
 
 
 enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg };
 enum kinds { w83627ehf, w83627dhg, w83627dhg_p, w83667hg };

+ 1 - 1
drivers/hwmon/w83627hf.c

@@ -51,7 +51,7 @@
 #include <linux/mutex.h>
 #include <linux/mutex.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
 #include <linux/acpi.h>
 #include <linux/acpi.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #include "lm75.h"
 #include "lm75.h"
 
 
 static struct platform_device *pdev;
 static struct platform_device *pdev;

+ 1 - 1
drivers/hwmon/w83781d.c

@@ -48,7 +48,7 @@
 #ifdef CONFIG_ISA
 #ifdef CONFIG_ISA
 #include <linux/platform_device.h>
 #include <linux/platform_device.h>
 #include <linux/ioport.h>
 #include <linux/ioport.h>
-#include <asm/io.h>
+#include <linux/io.h>
 #endif
 #endif
 
 
 #include "lm75.h"
 #include "lm75.h"