aboutsummaryrefslogtreecommitdiffstats
path: root/i2c
diff options
context:
space:
mode:
authorGreg Kroah-Hartman <gregkh@suse.de>2006-01-10 12:31:39 -0800
committerGreg Kroah-Hartman <gregkh@suse.de>2006-01-10 12:31:39 -0800
commit9dcb2938b76dd4ee67232a6f812117b8097a85c1 (patch)
treeeada5738bbd6d44e149ca8ab861dee25a0246a66 /i2c
parent3871c527fe1cef5a8a6a5cd4613e0f583307a4dc (diff)
downloadpatches-9dcb2938b76dd4ee67232a6f812117b8097a85c1.tar.gz
more patches added
Diffstat (limited to 'i2c')
-rw-r--r--i2c/hwmon-allow-sensor-attr-arrays.patch46
-rw-r--r--i2c/hwmon-f71805f-add-documentation.patch125
-rw-r--r--i2c/hwmon-f71805f-new-driver.patch1021
-rw-r--r--i2c/hwmon-f71805f-use-attr-arrays.patch307
-rw-r--r--i2c/hwmon-lm77-negative-temp-fix.patch40
-rw-r--r--i2c/hwmon-pc87360-use-attr-arrays.patch567
-rw-r--r--i2c/hwmon-w83792d-inline-register-access-functions.patch72
-rw-r--r--i2c/i2c-algo-sibyte-module-param.patch32
-rw-r--r--i2c/i2c-busses-use-array-size-macro.patch82
-rw-r--r--i2c/i2c-sis96x-rename-documentation.patch174
10 files changed, 2466 insertions, 0 deletions
diff --git a/i2c/hwmon-allow-sensor-attr-arrays.patch b/i2c/hwmon-allow-sensor-attr-arrays.patch
new file mode 100644
index 0000000000000..398bd26fa255f
--- /dev/null
+++ b/i2c/hwmon-allow-sensor-attr-arrays.patch
@@ -0,0 +1,46 @@
+From khali@linux-fr.org Mon Jan 9 14:27:40 2006
+Date: Mon, 9 Jan 2006 23:22:24 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Jim Cromie <jim.cromie@gmail.com>
+Subject: hwmon: Allow sensor attributes arrays
+Message-Id: <20060109232224.053ae9ff.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-allow-sensor-attr-arrays.patch
+
+From: Jim Cromie <jim.cromie@gmail.com>
+
+This patch refactors SENSOR_DEVICE_ATTR macro. First it creates a new
+macro SENSOR_ATTR() which expands to an initialization expression, then
+it uses that in SENSOR_DEVICE_ATTR, which declares and initializes a
+struct sensor_device_attribute.
+
+IOW, SENSOR_ATTR() imitates __ATTR() in include/linux/device.h.
+
+Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ include/linux/hwmon-sysfs.h | 12 +++++++-----
+ 1 file changed, 7 insertions(+), 5 deletions(-)
+
+--- gregkh-2.6.orig/include/linux/hwmon-sysfs.h
++++ gregkh-2.6/include/linux/hwmon-sysfs.h
+@@ -27,11 +27,13 @@ struct sensor_device_attribute{
+ #define to_sensor_dev_attr(_dev_attr) \
+ container_of(_dev_attr, struct sensor_device_attribute, dev_attr)
+
+-#define SENSOR_DEVICE_ATTR(_name,_mode,_show,_store,_index) \
+-struct sensor_device_attribute sensor_dev_attr_##_name = { \
+- .dev_attr = __ATTR(_name,_mode,_show,_store), \
+- .index = _index, \
+-}
++#define SENSOR_ATTR(_name, _mode, _show, _store, _index) \
++ { .dev_attr = __ATTR(_name, _mode, _show, _store), \
++ .index = _index }
++
++#define SENSOR_DEVICE_ATTR(_name, _mode, _show, _store, _index) \
++struct sensor_device_attribute sensor_dev_attr_##_name \
++ = SENSOR_ATTR(_name, _mode, _show, _store, _index)
+
+ struct sensor_device_attribute_2 {
+ struct device_attribute dev_attr;
diff --git a/i2c/hwmon-f71805f-add-documentation.patch b/i2c/hwmon-f71805f-add-documentation.patch
new file mode 100644
index 0000000000000..f229dcc7fe932
--- /dev/null
+++ b/i2c/hwmon-f71805f-add-documentation.patch
@@ -0,0 +1,125 @@
+From khali@linux-fr.org Mon Jan 9 14:33:46 2006
+Date: Mon, 9 Jan 2006 23:32:57 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Subject: hwmon: Add f71805f documentation
+Message-Id: <20060109233257.7ae91910.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-f71805f-add-documentation.patch
+
+Add some documentation for the new f71805f driver. This is almost the
+same help that was present in lm_sensors, with a few minor layout fixes.
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ Documentation/hwmon/f71805f | 105 ++++++++++++++++++++++++++++++++++++++++++++
+ 1 file changed, 105 insertions(+)
+
+--- /dev/null
++++ gregkh-2.6/Documentation/hwmon/f71805f
+@@ -0,0 +1,105 @@
++Kernel driver f71805f
++=====================
++
++Supported chips:
++ * Fintek F71805F/FG
++ Prefix: 'f71805f'
++ Addresses scanned: none, address read from Super I/O config space
++ Datasheet: Provided by Fintek on request
++
++Author: Jean Delvare <khali@linux-fr.org>
++
++Thanks to Denis Kieft from Barracuda Networks for the donation of a
++test system (custom Jetway K8M8MS motherboard, with CPU and RAM) and
++for providing initial documentation.
++
++Thanks to Kris Chen from Fintek for answering technical questions and
++providing additional documentation.
++
++Thanks to Chris Lin from Jetway for providing wiring schematics and
++anwsering technical questions.
++
++
++Description
++-----------
++
++The Fintek F71805F/FG Super I/O chip includes complete hardware monitoring
++capabilities. It can monitor up to 9 voltages (counting its own power
++source), 3 fans and 3 temperature sensors.
++
++This chip also has fan controlling features, using either DC or PWM, in
++three different modes (one manual, two automatic). The driver doesn't
++support these features yet.
++
++The driver assumes that no more than one chip is present, which seems
++reasonable.
++
++
++Voltage Monitoring
++------------------
++
++Voltages are sampled by an 8-bit ADC with a LSB of 8 mV. The supported
++range is thus from 0 to 2.040 V. Voltage values outside of this range
++need external resistors. An exception is in0, which is used to monitor
++the chip's own power source (+3.3V), and is divided internally by a
++factor 2.
++
++The two LSB of the voltage limit registers are not used (always 0), so
++you can only set the limits in steps of 32 mV (before scaling).
++
++The wirings and resistor values suggested by Fintek are as follow:
++
++ pin expected
++ name use R1 R2 divider raw val.
++
++in0 VCC VCC3.3V int. int. 2.00 1.65 V
++in1 VIN1 VTT1.2V 10K - 1.00 1.20 V
++in2 VIN2 VRAM 100K 100K 2.00 ~1.25 V (1)
++in3 VIN3 VCHIPSET 47K 100K 1.47 2.24 V (2)
++in4 VIN4 VCC5V 200K 47K 5.25 0.95 V
++in5 VIN5 +12V 200K 20K 11.00 1.05 V
++in6 VIN6 VCC1.5V 10K - 1.00 1.50 V
++in7 VIN7 VCORE 10K - 1.00 ~1.40 V (1)
++in8 VIN8 VSB5V 200K 47K 1.00 0.95 V
++
++(1) Depends on your hardware setup.
++(2) Obviously not correct, swapping R1 and R2 would make more sense.
++
++These values can be used as hints at best, as motherboard manufacturers
++are free to use a completely different setup. As a matter of fact, the
++Jetway K8M8MS uses a significantly different setup. You will have to
++find out documentation about your own motherboard, and edit sensors.conf
++accordingly.
++
++Each voltage measured has associated low and high limits, each of which
++triggers an alarm when crossed.
++
++
++Fan Monitoring
++--------------
++
++Fan rotation speeds are reported as 12-bit values from a gated clock
++signal. Speeds down to 366 RPM can be measured. There is no theoretical
++high limit, but values over 6000 RPM seem to cause problem. The effective
++resolution is much lower than you would expect, the step between different
++register values being 10 rather than 1.
++
++The chip assumes 2 pulse-per-revolution fans.
++
++An alarm is triggered if the rotation speed drops below a programmable
++limit or is too low to be measured.
++
++
++Temperature Monitoring
++----------------------
++
++Temperatures are reported in degrees Celsius. Each temperature measured
++has a high limit, those crossing triggers an alarm. There is an associated
++hysteresis value, below which the temperature has to drop before the
++alarm is cleared.
++
++All temperature channels are external, there is no embedded temperature
++sensor. Each channel can be used for connecting either a thermal diode
++or a thermistor. The driver reports the currently selected mode, but
++doesn't allow changing it. In theory, the BIOS should have configured
++everything properly.
diff --git a/i2c/hwmon-f71805f-new-driver.patch b/i2c/hwmon-f71805f-new-driver.patch
new file mode 100644
index 0000000000000..4804571e62288
--- /dev/null
+++ b/i2c/hwmon-f71805f-new-driver.patch
@@ -0,0 +1,1021 @@
+From khali@linux-fr.org Mon Jan 9 14:28:05 2006
+Date: Mon, 9 Jan 2006 23:26:14 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Subject: hwmon: New f71805f driver
+Message-Id: <20060109232614.35356061.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-f71805f-new-driver.patch
+
+This is my f71805f hardware monitoring driver ported from lm_sensors
+to Linux 2.6. This new driver differs from the other hardware monitoring
+drivers in that it is implemented as a platform driver. This might not
+be optimal yet (we would probably need a generic infrastructure and bus
+type for Super-I/O logical devices) but it is certainly much better than
+the i2c-isa solution.
+
+Note that this driver requires lm_sensors CVS. I hope to get it
+released as 2.10.0 soon.
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ Documentation/hwmon/sysfs-interface | 18
+ MAINTAINERS | 6
+ drivers/hwmon/Kconfig | 10
+ drivers/hwmon/Makefile | 1
+ drivers/hwmon/f71805f.c | 908 ++++++++++++++++++++++++++++++++++++
+ 5 files changed, 942 insertions(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/Documentation/hwmon/sysfs-interface
++++ gregkh-2.6/Documentation/hwmon/sysfs-interface
+@@ -179,11 +179,12 @@ temp[1-*]_auto_point[1-*]_temp_hyst
+ ****************
+
+ temp[1-3]_type Sensor type selection.
+- Integers 1, 2, 3 or thermistor Beta value (3435)
++ Integers 1 to 4 or thermistor Beta value (typically 3435)
+ Read/Write.
+ 1: PII/Celeron Diode
+ 2: 3904 transistor
+ 3: thermal diode
++ 4: thermistor (default/unknown Beta)
+ Not all types are supported by all chips
+
+ temp[1-4]_max Temperature max value.
+@@ -261,6 +262,21 @@ alarms Alarm bitmask.
+ of individual bits.
+ Bits are defined in kernel/include/sensors.h.
+
++alarms_in Alarm bitmask relative to in (voltage) channels
++ Read only
++ A '1' bit means an alarm, LSB corresponds to in0 and so on
++ Prefered to 'alarms' for newer chips
++
++alarms_fan Alarm bitmask relative to fan channels
++ Read only
++ A '1' bit means an alarm, LSB corresponds to fan1 and so on
++ Prefered to 'alarms' for newer chips
++
++alarms_temp Alarm bitmask relative to temp (temperature) channels
++ Read only
++ A '1' bit means an alarm, LSB corresponds to temp1 and so on
++ Prefered to 'alarms' for newer chips
++
+ beep_enable Beep/interrupt enable
+ 0 to disable.
+ 1 to enable.
+--- gregkh-2.6.orig/drivers/hwmon/Kconfig
++++ gregkh-2.6/drivers/hwmon/Kconfig
+@@ -113,6 +113,16 @@ config SENSORS_DS1621
+ This driver can also be built as a module. If so, the module
+ will be called ds1621.
+
++config SENSORS_F71805F
++ tristate "Fintek F71805F/FG"
++ depends on HWMON && EXPERIMENTAL
++ help
++ If you say yes here you get support for hardware monitoring
++ features of the Fintek F71805F/FG chips.
++
++ This driver can also be built as a module. If so, the module
++ will be called f71805f.
++
+ config SENSORS_FSCHER
+ tristate "FSC Hermes"
+ depends on HWMON && I2C && EXPERIMENTAL
+--- gregkh-2.6.orig/drivers/hwmon/Makefile
++++ gregkh-2.6/drivers/hwmon/Makefile
+@@ -18,6 +18,7 @@ obj-$(CONFIG_SENSORS_ADM1031) += adm1031
+ obj-$(CONFIG_SENSORS_ADM9240) += adm9240.o
+ obj-$(CONFIG_SENSORS_ATXP1) += atxp1.o
+ obj-$(CONFIG_SENSORS_DS1621) += ds1621.o
++obj-$(CONFIG_SENSORS_F71805F) += f71805f.o
+ obj-$(CONFIG_SENSORS_FSCHER) += fscher.o
+ obj-$(CONFIG_SENSORS_FSCPOS) += fscpos.o
+ obj-$(CONFIG_SENSORS_GL518SM) += gl518sm.o
+--- /dev/null
++++ gregkh-2.6/drivers/hwmon/f71805f.c
+@@ -0,0 +1,908 @@
++/*
++ * f71805f.c - driver for the Fintek F71805F/FG Super-I/O chip integrated
++ * hardware monitoring features
++ * Copyright (C) 2005 Jean Delvare <khali@linux-fr.org>
++ *
++ * The F71805F/FG is a LPC Super-I/O chip made by Fintek. It integrates
++ * complete hardware monitoring features: voltage, fan and temperature
++ * sensors, and manual and automatic fan speed control.
++ *
++ * This program is free software; you can redistribute it and/or modify
++ * it under the terms of the GNU General Public License as published by
++ * the Free Software Foundation; either version 2 of the License, or
++ * (at your option) any later version.
++ *
++ * This program is distributed in the hope that it will be useful,
++ * but WITHOUT ANY WARRANTY; without even the implied warranty of
++ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
++ * GNU General Public License for more details.
++ *
++ * You should have received a copy of the GNU General Public License
++ * along with this program; if not, write to the Free Software
++ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
++ */
++
++#include <linux/module.h>
++#include <linux/init.h>
++#include <linux/slab.h>
++#include <linux/jiffies.h>
++#include <linux/platform_device.h>
++#include <linux/hwmon.h>
++#include <linux/hwmon-sysfs.h>
++#include <linux/err.h>
++#include <asm/io.h>
++
++static struct platform_device *pdev;
++
++#define DRVNAME "f71805f"
++
++/*
++ * Super-I/O constants and functions
++ */
++
++#define F71805F_LD_HWM 0x04
++
++#define SIO_REG_LDSEL 0x07 /* Logical device select */
++#define SIO_REG_DEVID 0x20 /* Device ID (2 bytes) */
++#define SIO_REG_DEVREV 0x22 /* Device revision */
++#define SIO_REG_MANID 0x23 /* Fintek ID (2 bytes) */
++#define SIO_REG_ENABLE 0x30 /* Logical device enable */
++#define SIO_REG_ADDR 0x60 /* Logical device address (2 bytes) */
++
++#define SIO_FINTEK_ID 0x1934
++#define SIO_F71805F_ID 0x0406
++
++static inline int
++superio_inb(int base, int reg)
++{
++ outb(reg, base);
++ return inb(base + 1);
++}
++
++static int
++superio_inw(int base, int reg)
++{
++ int val;
++ outb(reg++, base);
++ val = inb(base + 1) << 8;
++ outb(reg, base);
++ val |= inb(base + 1);
++ return val;
++}
++
++static inline void
++superio_select(int base, int ld)
++{
++ outb(SIO_REG_LDSEL, base);
++ outb(ld, base + 1);
++}
++
++static inline void
++superio_enter(int base)
++{
++ outb(0x87, base);
++ outb(0x87, base);
++}
++
++static inline void
++superio_exit(int base)
++{
++ outb(0xaa, base);
++}
++
++/*
++ * ISA constants
++ */
++
++#define REGION_LENGTH 2
++#define ADDR_REG_OFFSET 0
++#define DATA_REG_OFFSET 1
++
++static struct resource f71805f_resource __initdata = {
++ .flags = IORESOURCE_IO,
++};
++
++/*
++ * Registers
++ */
++
++/* in nr from 0 to 8 (8-bit values) */
++#define F71805F_REG_IN(nr) (0x10 + (nr))
++#define F71805F_REG_IN_HIGH(nr) (0x40 + 2 * (nr))
++#define F71805F_REG_IN_LOW(nr) (0x41 + 2 * (nr))
++/* fan nr from 0 to 2 (12-bit values, two registers) */
++#define F71805F_REG_FAN(nr) (0x20 + 2 * (nr))
++#define F71805F_REG_FAN_LOW(nr) (0x28 + 2 * (nr))
++#define F71805F_REG_FAN_CTRL(nr) (0x60 + 16 * (nr))
++/* temp nr from 0 to 2 (8-bit values) */
++#define F71805F_REG_TEMP(nr) (0x1B + (nr))
++#define F71805F_REG_TEMP_HIGH(nr) (0x54 + 2 * (nr))
++#define F71805F_REG_TEMP_HYST(nr) (0x55 + 2 * (nr))
++#define F71805F_REG_TEMP_MODE 0x01
++
++#define F71805F_REG_START 0x00
++/* status nr from 0 to 2 */
++#define F71805F_REG_STATUS(nr) (0x36 + (nr))
++
++/*
++ * Data structures and manipulation thereof
++ */
++
++struct f71805f_data {
++ unsigned short addr;
++ const char *name;
++ struct semaphore lock;
++ struct class_device *class_dev;
++
++ struct semaphore update_lock;
++ char valid; /* !=0 if following fields are valid */
++ unsigned long last_updated; /* In jiffies */
++ unsigned long last_limits; /* In jiffies */
++
++ /* Register values */
++ u8 in[9];
++ u8 in_high[9];
++ u8 in_low[9];
++ u16 fan[3];
++ u16 fan_low[3];
++ u8 fan_enabled; /* Read once at init time */
++ u8 temp[3];
++ u8 temp_high[3];
++ u8 temp_hyst[3];
++ u8 temp_mode;
++ u8 alarms[3];
++};
++
++static inline long in_from_reg(u8 reg)
++{
++ return (reg * 8);
++}
++
++/* The 2 least significant bits are not used */
++static inline u8 in_to_reg(long val)
++{
++ if (val <= 0)
++ return 0;
++ if (val >= 2016)
++ return 0xfc;
++ return (((val + 16) / 32) << 2);
++}
++
++/* in0 is downscaled by a factor 2 internally */
++static inline long in0_from_reg(u8 reg)
++{
++ return (reg * 16);
++}
++
++static inline u8 in0_to_reg(long val)
++{
++ if (val <= 0)
++ return 0;
++ if (val >= 4032)
++ return 0xfc;
++ return (((val + 32) / 64) << 2);
++}
++
++/* The 4 most significant bits are not used */
++static inline long fan_from_reg(u16 reg)
++{
++ reg &= 0xfff;
++ if (!reg || reg == 0xfff)
++ return 0;
++ return (1500000 / reg);
++}
++
++static inline u16 fan_to_reg(long rpm)
++{
++ /* If the low limit is set below what the chip can measure,
++ store the largest possible 12-bit value in the registers,
++ so that no alarm will ever trigger. */
++ if (rpm < 367)
++ return 0xfff;
++ return (1500000 / rpm);
++}
++
++static inline long temp_from_reg(u8 reg)
++{
++ return (reg * 1000);
++}
++
++static inline u8 temp_to_reg(long val)
++{
++ if (val < 0)
++ val = 0;
++ else if (val > 1000 * 0xff)
++ val = 0xff;
++ return ((val + 500) / 1000);
++}
++
++/*
++ * Device I/O access
++ */
++
++static u8 f71805f_read8(struct f71805f_data *data, u8 reg)
++{
++ u8 val;
++
++ down(&data->lock);
++ outb(reg, data->addr + ADDR_REG_OFFSET);
++ val = inb(data->addr + DATA_REG_OFFSET);
++ up(&data->lock);
++
++ return val;
++}
++
++static void f71805f_write8(struct f71805f_data *data, u8 reg, u8 val)
++{
++ down(&data->lock);
++ outb(reg, data->addr + ADDR_REG_OFFSET);
++ outb(val, data->addr + DATA_REG_OFFSET);
++ up(&data->lock);
++}
++
++/* It is important to read the MSB first, because doing so latches the
++ value of the LSB, so we are sure both bytes belong to the same value. */
++static u16 f71805f_read16(struct f71805f_data *data, u8 reg)
++{
++ u16 val;
++
++ down(&data->lock);
++ outb(reg, data->addr + ADDR_REG_OFFSET);
++ val = inb(data->addr + DATA_REG_OFFSET) << 8;
++ outb(++reg, data->addr + ADDR_REG_OFFSET);
++ val |= inb(data->addr + DATA_REG_OFFSET);
++ up(&data->lock);
++
++ return val;
++}
++
++static void f71805f_write16(struct f71805f_data *data, u8 reg, u16 val)
++{
++ down(&data->lock);
++ outb(reg, data->addr + ADDR_REG_OFFSET);
++ outb(val >> 8, data->addr + DATA_REG_OFFSET);
++ outb(++reg, data->addr + ADDR_REG_OFFSET);
++ outb(val & 0xff, data->addr + DATA_REG_OFFSET);
++ up(&data->lock);
++}
++
++static struct f71805f_data *f71805f_update_device(struct device *dev)
++{
++ struct f71805f_data *data = dev_get_drvdata(dev);
++ int nr;
++
++ down(&data->update_lock);
++
++ /* Limit registers cache is refreshed after 60 seconds */
++ if (time_after(jiffies, data->last_updated + 60 * HZ)
++ || !data->valid) {
++ for (nr = 0; nr < 9; nr++) {
++ data->in_high[nr] = f71805f_read8(data,
++ F71805F_REG_IN_HIGH(nr));
++ data->in_low[nr] = f71805f_read8(data,
++ F71805F_REG_IN_LOW(nr));
++ }
++ for (nr = 0; nr < 3; nr++) {
++ if (data->fan_enabled & (1 << nr))
++ data->fan_low[nr] = f71805f_read16(data,
++ F71805F_REG_FAN_LOW(nr));
++ }
++ for (nr = 0; nr < 3; nr++) {
++ data->temp_high[nr] = f71805f_read8(data,
++ F71805F_REG_TEMP_HIGH(nr));
++ data->temp_hyst[nr] = f71805f_read8(data,
++ F71805F_REG_TEMP_HYST(nr));
++ }
++ data->temp_mode = f71805f_read8(data, F71805F_REG_TEMP_MODE);
++
++ data->last_limits = jiffies;
++ }
++
++ /* Measurement registers cache is refreshed after 1 second */
++ if (time_after(jiffies, data->last_updated + HZ)
++ || !data->valid) {
++ for (nr = 0; nr < 9; nr++) {
++ data->in[nr] = f71805f_read8(data,
++ F71805F_REG_IN(nr));
++ }
++ for (nr = 0; nr < 3; nr++) {
++ if (data->fan_enabled & (1 << nr))
++ data->fan[nr] = f71805f_read16(data,
++ F71805F_REG_FAN(nr));
++ }
++ for (nr = 0; nr < 3; nr++) {
++ data->temp[nr] = f71805f_read8(data,
++ F71805F_REG_TEMP(nr));
++ }
++ for (nr = 0; nr < 3; nr++) {
++ data->alarms[nr] = f71805f_read8(data,
++ F71805F_REG_STATUS(nr));
++ }
++
++ data->last_updated = jiffies;
++ data->valid = 1;
++ }
++
++ up(&data->update_lock);
++
++ return data;
++}
++
++/*
++ * Sysfs interface
++ */
++
++static ssize_t show_in0(struct device *dev, struct device_attribute *devattr,
++ char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++
++ return sprintf(buf, "%ld\n", in0_from_reg(data->in[0]));
++}
++
++static ssize_t show_in0_max(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++
++ return sprintf(buf, "%ld\n", in0_from_reg(data->in_high[0]));
++}
++
++static ssize_t show_in0_min(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++
++ return sprintf(buf, "%ld\n", in0_from_reg(data->in_low[0]));
++}
++
++static ssize_t set_in0_max(struct device *dev, struct device_attribute
++ *devattr, const char *buf, size_t count)
++{
++ struct f71805f_data *data = dev_get_drvdata(dev);
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->in_high[0] = in0_to_reg(val);
++ f71805f_write8(data, F71805F_REG_IN_HIGH(0), data->in_high[0]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++static ssize_t set_in0_min(struct device *dev, struct device_attribute
++ *devattr, const char *buf, size_t count)
++{
++ struct f71805f_data *data = dev_get_drvdata(dev);
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->in_low[0] = in0_to_reg(val);
++ f71805f_write8(data, F71805F_REG_IN_LOW(0), data->in_low[0]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
++static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
++static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
++
++static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
++ char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", in_from_reg(data->in[nr]));
++}
++
++static ssize_t show_in_max(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", in_from_reg(data->in_high[nr]));
++}
++
++static ssize_t show_in_min(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", in_from_reg(data->in_low[nr]));
++}
++
++static ssize_t set_in_max(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 *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->in_high[nr] = in_to_reg(val);
++ f71805f_write8(data, F71805F_REG_IN_HIGH(nr), data->in_high[nr]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++static ssize_t set_in_min(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 *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->in_low[nr] = in_to_reg(val);
++ f71805f_write8(data, F71805F_REG_IN_LOW(nr), data->in_low[nr]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++#define sysfs_in(offset) \
++static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
++ show_in, NULL, offset); \
++static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
++ show_in_max, set_in_max, offset); \
++static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
++ show_in_min, set_in_min, offset)
++
++sysfs_in(1);
++sysfs_in(2);
++sysfs_in(3);
++sysfs_in(4);
++sysfs_in(5);
++sysfs_in(6);
++sysfs_in(7);
++sysfs_in(8);
++
++static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
++ char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", fan_from_reg(data->fan[nr]));
++}
++
++static ssize_t show_fan_min(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", fan_from_reg(data->fan_low[nr]));
++}
++
++static ssize_t set_fan_min(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 *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->fan_low[nr] = fan_to_reg(val);
++ f71805f_write16(data, F71805F_REG_FAN_LOW(nr), data->fan_low[nr]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++#define sysfs_fan(offset) \
++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)
++
++sysfs_fan(1);
++sysfs_fan(2);
++sysfs_fan(3);
++
++static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
++ char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", temp_from_reg(data->temp[nr]));
++}
++
++static ssize_t show_temp_max(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", temp_from_reg(data->temp_high[nr]));
++}
++
++static ssize_t show_temp_hyst(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ return sprintf(buf, "%ld\n", temp_from_reg(data->temp_hyst[nr]));
++}
++
++static ssize_t show_temp_type(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++ struct sensor_device_attribute *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++
++ /* 3 is diode, 4 is thermistor */
++ return sprintf(buf, "%u\n", (data->temp_mode & (1 << nr)) ? 3 : 4);
++}
++
++static ssize_t set_temp_max(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 *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->temp_high[nr] = temp_to_reg(val);
++ f71805f_write8(data, F71805F_REG_TEMP_HIGH(nr), data->temp_high[nr]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++static ssize_t set_temp_hyst(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 *attr = to_sensor_dev_attr(devattr);
++ int nr = attr->index;
++ long val = simple_strtol(buf, NULL, 10);
++
++ down(&data->update_lock);
++ data->temp_hyst[nr] = temp_to_reg(val);
++ f71805f_write8(data, F71805F_REG_TEMP_HYST(nr), data->temp_hyst[nr]);
++ up(&data->update_lock);
++
++ return count;
++}
++
++#define sysfs_temp(offset) \
++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_max, set_temp_max, offset - 1); \
++static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
++ show_temp_hyst, set_temp_hyst, offset - 1); \
++static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \
++ show_temp_type, NULL, offset - 1)
++
++sysfs_temp(1);
++sysfs_temp(2);
++sysfs_temp(3);
++
++static ssize_t show_alarms_in(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++
++ return sprintf(buf, "%d\n", data->alarms[0] |
++ ((data->alarms[1] & 0x01) << 8));
++}
++
++static ssize_t show_alarms_fan(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++
++ return sprintf(buf, "%d\n", data->alarms[2] & 0x07);
++}
++
++static ssize_t show_alarms_temp(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = f71805f_update_device(dev);
++
++ return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
++}
++
++static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
++static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
++static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
++
++static ssize_t show_name(struct device *dev, struct device_attribute
++ *devattr, char *buf)
++{
++ struct f71805f_data *data = dev_get_drvdata(dev);
++
++ return sprintf(buf, "%s\n", data->name);
++}
++
++static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
++
++/*
++ * Device registration and initialization
++ */
++
++static void __devinit f71805f_init_device(struct f71805f_data *data)
++{
++ u8 reg;
++ int i;
++
++ reg = f71805f_read8(data, F71805F_REG_START);
++ if ((reg & 0x41) != 0x01) {
++ printk(KERN_DEBUG DRVNAME ": Starting monitoring "
++ "operations\n");
++ f71805f_write8(data, F71805F_REG_START, (reg | 0x01) & ~0x40);
++ }
++
++ /* Fan monitoring can be disabled. If it is, we won't be polling
++ the register values, and won't create the related sysfs files. */
++ for (i = 0; i < 3; i++) {
++ reg = f71805f_read8(data, F71805F_REG_FAN_CTRL(i));
++ if (!(reg & 0x80))
++ data->fan_enabled |= (1 << i);
++ }
++}
++
++static int __devinit f71805f_probe(struct platform_device *pdev)
++{
++ struct f71805f_data *data;
++ struct resource *res;
++ int err;
++
++ if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
++ err = -ENOMEM;
++ printk(KERN_ERR DRVNAME ": Out of memory\n");
++ goto exit;
++ }
++
++ res = platform_get_resource(pdev, IORESOURCE_IO, 0);
++ data->addr = res->start;
++ init_MUTEX(&data->lock);
++ data->name = "f71805f";
++ init_MUTEX(&data->update_lock);
++
++ platform_set_drvdata(pdev, data);
++
++ data->class_dev = hwmon_device_register(&pdev->dev);
++ if (IS_ERR(data->class_dev)) {
++ err = PTR_ERR(data->class_dev);
++ dev_err(&pdev->dev, "Class registration failed (%d)\n", err);
++ goto exit_free;
++ }
++
++ /* Initialize the F71805F chip */
++ f71805f_init_device(data);
++
++ /* Register sysfs interface files */
++ device_create_file(&pdev->dev, &dev_attr_in0_input);
++ device_create_file(&pdev->dev, &dev_attr_in0_max);
++ device_create_file(&pdev->dev, &dev_attr_in0_min);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr);
++ if (data->fan_enabled & (1 << 0)) {
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_fan1_input.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_fan1_min.dev_attr);
++ }
++ if (data->fan_enabled & (1 << 1)) {
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_fan2_input.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_fan2_min.dev_attr);
++ }
++ if (data->fan_enabled & (1 << 2)) {
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_fan3_input.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_fan3_min.dev_attr);
++ }
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_temp1_input.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_temp2_input.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_temp3_input.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_temp1_max_hyst.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_temp2_max_hyst.dev_attr);
++ device_create_file(&pdev->dev,
++ &sensor_dev_attr_temp3_max_hyst.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr);
++ device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr);
++ device_create_file(&pdev->dev, &dev_attr_alarms_in);
++ device_create_file(&pdev->dev, &dev_attr_alarms_fan);
++ device_create_file(&pdev->dev, &dev_attr_alarms_temp);
++ device_create_file(&pdev->dev, &dev_attr_name);
++
++ return 0;
++
++exit_free:
++ kfree(data);
++exit:
++ return err;
++}
++
++static int __devexit f71805f_remove(struct platform_device *pdev)
++{
++ struct f71805f_data *data = platform_get_drvdata(pdev);
++
++ platform_set_drvdata(pdev, NULL);
++ hwmon_device_unregister(data->class_dev);
++ kfree(data);
++
++ return 0;
++}
++
++static struct platform_driver f71805f_driver = {
++ .driver = {
++ .owner = THIS_MODULE,
++ .name = DRVNAME,
++ },
++ .probe = f71805f_probe,
++ .remove = __devexit_p(f71805f_remove),
++};
++
++static int __init f71805f_device_add(unsigned short address)
++{
++ int err;
++
++ pdev = platform_device_alloc(DRVNAME, address);
++ if (!pdev) {
++ err = -ENOMEM;
++ printk(KERN_ERR DRVNAME ": Device allocation failed\n");
++ goto exit;
++ }
++
++ f71805f_resource.start = address;
++ f71805f_resource.end = address + REGION_LENGTH - 1;
++ f71805f_resource.name = pdev->name;
++ err = platform_device_add_resources(pdev, &f71805f_resource, 1);
++ if (err) {
++ printk(KERN_ERR DRVNAME ": Device resource addition failed "
++ "(%d)\n", err);
++ goto exit_device_put;
++ }
++
++ err = platform_device_add(pdev);
++ if (err) {
++ printk(KERN_ERR DRVNAME ": Device addition failed (%d)\n",
++ err);
++ goto exit_device_put;
++ }
++
++ return 0;
++
++exit_device_put:
++ platform_device_put(pdev);
++exit:
++ return err;
++}
++
++static int __init f71805f_find(int sioaddr, unsigned short *address)
++{
++ int err = -ENODEV;
++ u16 devid;
++
++ superio_enter(sioaddr);
++
++ devid = superio_inw(sioaddr, SIO_REG_MANID);
++ if (devid != SIO_FINTEK_ID)
++ goto exit;
++
++ devid = superio_inw(sioaddr, SIO_REG_DEVID);
++ if (devid != SIO_F71805F_ID) {
++ printk(KERN_INFO DRVNAME ": Unsupported Fintek device, "
++ "skipping\n");
++ goto exit;
++ }
++
++ superio_select(sioaddr, F71805F_LD_HWM);
++ if (!(superio_inb(sioaddr, SIO_REG_ENABLE) & 0x01)) {
++ printk(KERN_WARNING DRVNAME ": Device not activated, "
++ "skipping\n");
++ goto exit;
++ }
++
++ *address = superio_inw(sioaddr, SIO_REG_ADDR);
++ if (*address == 0) {
++ printk(KERN_WARNING DRVNAME ": Base address not set, "
++ "skipping\n");
++ goto exit;
++ }
++
++ err = 0;
++ printk(KERN_INFO DRVNAME ": Found F71805F chip at %#x, revision %u\n",
++ *address, superio_inb(sioaddr, SIO_REG_DEVREV));
++
++exit:
++ superio_exit(sioaddr);
++ return err;
++}
++
++static int __init f71805f_init(void)
++{
++ int err;
++ unsigned short address;
++
++ if (f71805f_find(0x2e, &address)
++ && f71805f_find(0x4e, &address))
++ return -ENODEV;
++
++ err = platform_driver_register(&f71805f_driver);
++ if (err)
++ goto exit;
++
++ /* Sets global pdev as a side effect */
++ err = f71805f_device_add(address);
++ if (err)
++ goto exit_driver;
++
++ return 0;
++
++exit_driver:
++ platform_driver_unregister(&f71805f_driver);
++exit:
++ return err;
++}
++
++static void __exit f71805f_exit(void)
++{
++ platform_device_unregister(pdev);
++ platform_driver_unregister(&f71805f_driver);
++}
++
++MODULE_AUTHOR("Jean Delvare <khali@linux-fr>");
++MODULE_LICENSE("GPL");
++MODULE_DESCRIPTION("F71805F hardware monitoring driver");
++
++module_init(f71805f_init);
++module_exit(f71805f_exit);
+--- gregkh-2.6.orig/MAINTAINERS
++++ gregkh-2.6/MAINTAINERS
+@@ -917,6 +917,12 @@ M: sct@redhat.com, akpm@osdl.org, adilge
+ L: ext3-users@redhat.com
+ S: Maintained
+
++F71805F HARDWARE MONITORING DRIVER
++P: Jean Delvare
++M: khali@linux-fr.org
++L: lm-sensors@lm-sensors.org
++S: Maintained
++
+ FARSYNC SYNCHRONOUS DRIVER
+ P: Kevin Curtis
+ M: kevin.curtis@farsite.co.uk
diff --git a/i2c/hwmon-f71805f-use-attr-arrays.patch b/i2c/hwmon-f71805f-use-attr-arrays.patch
new file mode 100644
index 0000000000000..92b5908ed71fa
--- /dev/null
+++ b/i2c/hwmon-f71805f-use-attr-arrays.patch
@@ -0,0 +1,307 @@
+From khali@linux-fr.org Mon Jan 9 14:33:39 2006
+Date: Mon, 9 Jan 2006 23:29:11 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Subject: hwmon: Use attribute arrays in f71805f
+Message-Id: <20060109232911.7370e554.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-f71805f-use-attr-arrays.patch
+
+Convert the f71805f driver to use arrays of attributes. This shrinks the
+compiled module from 12.0 kB to 9.6 kB. We certainly should do the same
+for as many hardware monitoring drivers as possible.
+
+This, together with a nice chip design by Fintek, makes this driver
+very small, both in terms of number of lines of code and memory
+consumption.
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/hwmon/f71805f.c | 224 ++++++++++++++++++++++--------------------------
+ 1 file changed, 106 insertions(+), 118 deletions(-)
+
+--- gregkh-2.6.orig/drivers/hwmon/f71805f.c
++++ gregkh-2.6/drivers/hwmon/f71805f.c
+@@ -384,10 +384,6 @@ static ssize_t set_in0_min(struct device
+ return count;
+ }
+
+-static DEVICE_ATTR(in0_input, S_IRUGO, show_in0, NULL);
+-static DEVICE_ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max);
+-static DEVICE_ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min);
+-
+ static ssize_t show_in(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+ {
+@@ -450,23 +446,6 @@ static ssize_t set_in_min(struct device
+ return count;
+ }
+
+-#define sysfs_in(offset) \
+-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+- show_in, NULL, offset); \
+-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IRUGO | S_IWUSR, \
+- show_in_max, set_in_max, offset); \
+-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IRUGO | S_IWUSR, \
+- show_in_min, set_in_min, offset)
+-
+-sysfs_in(1);
+-sysfs_in(2);
+-sysfs_in(3);
+-sysfs_in(4);
+-sysfs_in(5);
+-sysfs_in(6);
+-sysfs_in(7);
+-sysfs_in(8);
+-
+ static ssize_t show_fan(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+ {
+@@ -503,16 +482,6 @@ static ssize_t set_fan_min(struct device
+ return count;
+ }
+
+-#define sysfs_fan(offset) \
+-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)
+-
+-sysfs_fan(1);
+-sysfs_fan(2);
+-sysfs_fan(3);
+-
+ static ssize_t show_temp(struct device *dev, struct device_attribute *devattr,
+ char *buf)
+ {
+@@ -586,20 +555,6 @@ static ssize_t set_temp_hyst(struct devi
+ return count;
+ }
+
+-#define sysfs_temp(offset) \
+-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_max, set_temp_max, offset - 1); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_max_hyst, S_IRUGO | S_IWUSR, \
+- show_temp_hyst, set_temp_hyst, offset - 1); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_type, S_IRUGO, \
+- show_temp_type, NULL, offset - 1)
+-
+-sysfs_temp(1);
+-sysfs_temp(2);
+-sysfs_temp(3);
+-
+ static ssize_t show_alarms_in(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+ {
+@@ -625,10 +580,6 @@ static ssize_t show_alarms_temp(struct d
+ return sprintf(buf, "%d\n", (data->alarms[1] >> 3) & 0x07);
+ }
+
+-static DEVICE_ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL);
+-static DEVICE_ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL);
+-static DEVICE_ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL);
+-
+ static ssize_t show_name(struct device *dev, struct device_attribute
+ *devattr, char *buf)
+ {
+@@ -637,7 +588,89 @@ static ssize_t show_name(struct device *
+ return sprintf(buf, "%s\n", data->name);
+ }
+
+-static DEVICE_ATTR(name, S_IRUGO, show_name, NULL);
++static struct device_attribute f71805f_dev_attr[] = {
++ __ATTR(in0_input, S_IRUGO, show_in0, NULL),
++ __ATTR(in0_max, S_IRUGO| S_IWUSR, show_in0_max, set_in0_max),
++ __ATTR(in0_min, S_IRUGO| S_IWUSR, show_in0_min, set_in0_min),
++ __ATTR(alarms_in, S_IRUGO, show_alarms_in, NULL),
++ __ATTR(alarms_fan, S_IRUGO, show_alarms_fan, NULL),
++ __ATTR(alarms_temp, S_IRUGO, show_alarms_temp, NULL),
++ __ATTR(name, S_IRUGO, show_name, NULL),
++};
++
++static struct sensor_device_attribute f71805f_sensor_attr[] = {
++ SENSOR_ATTR(in1_input, S_IRUGO, show_in, NULL, 1),
++ SENSOR_ATTR(in1_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 1),
++ SENSOR_ATTR(in1_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 1),
++ SENSOR_ATTR(in2_input, S_IRUGO, show_in, NULL, 2),
++ SENSOR_ATTR(in2_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 2),
++ SENSOR_ATTR(in2_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 2),
++ SENSOR_ATTR(in3_input, S_IRUGO, show_in, NULL, 3),
++ SENSOR_ATTR(in3_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 3),
++ SENSOR_ATTR(in3_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 3),
++ SENSOR_ATTR(in4_input, S_IRUGO, show_in, NULL, 4),
++ SENSOR_ATTR(in4_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 4),
++ SENSOR_ATTR(in4_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 4),
++ SENSOR_ATTR(in5_input, S_IRUGO, show_in, NULL, 5),
++ SENSOR_ATTR(in5_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 5),
++ SENSOR_ATTR(in5_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 5),
++ SENSOR_ATTR(in6_input, S_IRUGO, show_in, NULL, 6),
++ SENSOR_ATTR(in6_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 6),
++ SENSOR_ATTR(in6_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 6),
++ SENSOR_ATTR(in7_input, S_IRUGO, show_in, NULL, 7),
++ SENSOR_ATTR(in7_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 7),
++ SENSOR_ATTR(in7_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 7),
++ SENSOR_ATTR(in8_input, S_IRUGO, show_in, NULL, 8),
++ SENSOR_ATTR(in8_max, S_IRUGO | S_IWUSR,
++ show_in_max, set_in_max, 8),
++ SENSOR_ATTR(in8_min, S_IRUGO | S_IWUSR,
++ show_in_min, set_in_min, 8),
++
++ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0),
++ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
++ show_temp_max, set_temp_max, 0),
++ SENSOR_ATTR(temp1_max_hyst, S_IRUGO | S_IWUSR,
++ show_temp_hyst, set_temp_hyst, 0),
++ SENSOR_ATTR(temp1_type, S_IRUGO, show_temp_type, NULL, 0),
++ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1),
++ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
++ show_temp_max, set_temp_max, 1),
++ SENSOR_ATTR(temp2_max_hyst, S_IRUGO | S_IWUSR,
++ show_temp_hyst, set_temp_hyst, 1),
++ SENSOR_ATTR(temp2_type, S_IRUGO, show_temp_type, NULL, 1),
++ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp, NULL, 2),
++ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
++ show_temp_max, set_temp_max, 2),
++ SENSOR_ATTR(temp3_max_hyst, S_IRUGO | S_IWUSR,
++ show_temp_hyst, set_temp_hyst, 2),
++ SENSOR_ATTR(temp3_type, S_IRUGO, show_temp_type, NULL, 2),
++};
++
++static struct sensor_device_attribute f71805f_fan_attr[] = {
++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan, NULL, 0),
++ SENSOR_ATTR(fan1_min, S_IRUGO | S_IWUSR,
++ show_fan_min, set_fan_min, 0),
++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan, NULL, 1),
++ SENSOR_ATTR(fan2_min, S_IRUGO | S_IWUSR,
++ show_fan_min, set_fan_min, 1),
++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan, NULL, 2),
++ SENSOR_ATTR(fan3_min, S_IRUGO | S_IWUSR,
++ show_fan_min, set_fan_min, 2),
++};
+
+ /*
+ * Device registration and initialization
+@@ -668,7 +701,7 @@ static int __devinit f71805f_probe(struc
+ {
+ struct f71805f_data *data;
+ struct resource *res;
+- int err;
++ int i, err;
+
+ if (!(data = kzalloc(sizeof(struct f71805f_data), GFP_KERNEL))) {
+ err = -ENOMEM;
+@@ -695,76 +728,31 @@ static int __devinit f71805f_probe(struc
+ f71805f_init_device(data);
+
+ /* Register sysfs interface files */
+- device_create_file(&pdev->dev, &dev_attr_in0_input);
+- device_create_file(&pdev->dev, &dev_attr_in0_max);
+- device_create_file(&pdev->dev, &dev_attr_in0_min);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in1_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in2_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in3_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in4_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in5_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in6_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in7_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in8_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in1_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in2_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in3_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in4_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in5_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in6_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in7_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in8_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in1_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in2_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in3_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in4_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in5_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in6_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in7_min.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_in8_min.dev_attr);
+- if (data->fan_enabled & (1 << 0)) {
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_fan1_input.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_fan1_min.dev_attr);
+- }
+- if (data->fan_enabled & (1 << 1)) {
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_fan2_input.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_fan2_min.dev_attr);
+- }
+- if (data->fan_enabled & (1 << 2)) {
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_fan3_input.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_fan3_min.dev_attr);
+- }
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_temp1_input.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_temp2_input.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_temp3_input.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_temp1_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_temp2_max.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_temp3_max.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_temp1_max_hyst.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_temp2_max_hyst.dev_attr);
+- device_create_file(&pdev->dev,
+- &sensor_dev_attr_temp3_max_hyst.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_temp1_type.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_temp2_type.dev_attr);
+- device_create_file(&pdev->dev, &sensor_dev_attr_temp3_type.dev_attr);
+- device_create_file(&pdev->dev, &dev_attr_alarms_in);
+- device_create_file(&pdev->dev, &dev_attr_alarms_fan);
+- device_create_file(&pdev->dev, &dev_attr_alarms_temp);
+- device_create_file(&pdev->dev, &dev_attr_name);
++ for (i = 0; i < ARRAY_SIZE(f71805f_dev_attr); i++) {
++ err = device_create_file(&pdev->dev, &f71805f_dev_attr[i]);
++ if (err)
++ goto exit_class;
++ }
++ for (i = 0; i < ARRAY_SIZE(f71805f_sensor_attr); i++) {
++ err = device_create_file(&pdev->dev,
++ &f71805f_sensor_attr[i].dev_attr);
++ if (err)
++ goto exit_class;
++ }
++ for (i = 0; i < ARRAY_SIZE(f71805f_fan_attr); i++) {
++ if (!(data->fan_enabled & (1 << (i / 2))))
++ continue;
++ err = device_create_file(&pdev->dev,
++ &f71805f_fan_attr[i].dev_attr);
++ if (err)
++ goto exit_class;
++ }
+
+ return 0;
+
++exit_class:
++ dev_err(&pdev->dev, "Sysfs interface creation failed\n");
++ hwmon_device_unregister(data->class_dev);
+ exit_free:
+ kfree(data);
+ exit:
diff --git a/i2c/hwmon-lm77-negative-temp-fix.patch b/i2c/hwmon-lm77-negative-temp-fix.patch
new file mode 100644
index 0000000000000..036d6bb0bf169
--- /dev/null
+++ b/i2c/hwmon-lm77-negative-temp-fix.patch
@@ -0,0 +1,40 @@
+From khali@linux-fr.org Mon Jan 9 13:44:45 2006
+Date: Mon, 9 Jan 2006 22:43:08 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Michael Renzmann <mrenzmann@otaku42.de>
+Subject: hwmon: Fix negative temperature readings in lm77 driver
+Message-Id: <20060109224308.5b1637ba.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-lm77-negative-temp-fix.patch
+
+Fix negative temperature readings in lm77 driver.
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Acked-by: Michael Renzmann <mrenzmann@otaku42.de>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/hwmon/lm77.c | 8 ++++----
+ 1 file changed, 4 insertions(+), 4 deletions(-)
+
+--- gregkh-2.6.orig/drivers/hwmon/lm77.c
++++ gregkh-2.6/drivers/hwmon/lm77.c
+@@ -87,15 +87,15 @@ static struct i2c_driver lm77_driver = {
+
+ /* In the temperature registers, the low 3 bits are not part of the
+ temperature values; they are the status bits. */
+-static inline u16 LM77_TEMP_TO_REG(int temp)
++static inline s16 LM77_TEMP_TO_REG(int temp)
+ {
+ int ntemp = SENSORS_LIMIT(temp, LM77_TEMP_MIN, LM77_TEMP_MAX);
+- return (u16)((ntemp / 500) * 8);
++ return (ntemp / 500) * 8;
+ }
+
+-static inline int LM77_TEMP_FROM_REG(u16 reg)
++static inline int LM77_TEMP_FROM_REG(s16 reg)
+ {
+- return ((int)reg / 8) * 500;
++ return (reg / 8) * 500;
+ }
+
+ /* sysfs stuff */
diff --git a/i2c/hwmon-pc87360-use-attr-arrays.patch b/i2c/hwmon-pc87360-use-attr-arrays.patch
new file mode 100644
index 0000000000000..a964295686bc5
--- /dev/null
+++ b/i2c/hwmon-pc87360-use-attr-arrays.patch
@@ -0,0 +1,567 @@
+From khali@linux-fr.org Mon Jan 9 14:27:54 2006
+Date: Mon, 9 Jan 2006 23:24:41 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Jim Cromie <jim.cromie@gmail.com>
+Subject: hwmon: Use attribute arrays in pc87360
+Message-Id: <20060109232441.74164f74.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-pc87360-use-attr-arrays.patch
+
+From: Jim Cromie <jim.cromie@gmail.com>
+
+Convert individual sensors to sensor-attr arrays by each sensor type,
+and initialize them in loops instead of long blocks of individual calls.
+
+Signed-off-by: Jim Cromie <jim.cromie@gmail.com>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/hwmon/pc87360.c | 410 +++++++++++++++++++++++-------------------------
+ 1 file changed, 202 insertions(+), 208 deletions(-)
+
+--- gregkh-2.6.orig/drivers/hwmon/pc87360.c
++++ gregkh-2.6/drivers/hwmon/pc87360.c
+@@ -305,18 +305,26 @@ static ssize_t set_fan_min(struct device
+ return count;
+ }
+
+-#define show_and_set_fan(offset) \
+-static SENSOR_DEVICE_ATTR(fan##offset##_input, S_IRUGO, \
+- show_fan_input, NULL, offset-1); \
+-static SENSOR_DEVICE_ATTR(fan##offset##_min, S_IWUSR | S_IRUGO, \
+- show_fan_min, set_fan_min, offset-1); \
+-static SENSOR_DEVICE_ATTR(fan##offset##_div, S_IRUGO, \
+- show_fan_div, NULL, offset-1); \
+-static SENSOR_DEVICE_ATTR(fan##offset##_status, S_IRUGO, \
+- show_fan_status, NULL, offset-1);
+-show_and_set_fan(1)
+-show_and_set_fan(2)
+-show_and_set_fan(3)
++static struct sensor_device_attribute fan_input[] = {
++ SENSOR_ATTR(fan1_input, S_IRUGO, show_fan_input, NULL, 0),
++ SENSOR_ATTR(fan2_input, S_IRUGO, show_fan_input, NULL, 1),
++ SENSOR_ATTR(fan3_input, S_IRUGO, show_fan_input, NULL, 2),
++};
++static struct sensor_device_attribute fan_status[] = {
++ SENSOR_ATTR(fan1_status, S_IRUGO, show_fan_status, NULL, 0),
++ SENSOR_ATTR(fan2_status, S_IRUGO, show_fan_status, NULL, 1),
++ SENSOR_ATTR(fan3_status, S_IRUGO, show_fan_status, NULL, 2),
++};
++static struct sensor_device_attribute fan_div[] = {
++ SENSOR_ATTR(fan1_div, S_IRUGO, show_fan_div, NULL, 0),
++ SENSOR_ATTR(fan2_div, S_IRUGO, show_fan_div, NULL, 1),
++ SENSOR_ATTR(fan3_div, S_IRUGO, show_fan_div, NULL, 2),
++};
++static struct sensor_device_attribute fan_min[] = {
++ SENSOR_ATTR(fan1_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 0),
++ SENSOR_ATTR(fan2_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 1),
++ SENSOR_ATTR(fan3_min, S_IWUSR | S_IRUGO, show_fan_min, set_fan_min, 2),
++};
+
+ static ssize_t show_pwm(struct device *dev, struct device_attribute *devattr, char *buf)
+ {
+@@ -344,12 +352,11 @@ static ssize_t set_pwm(struct device *de
+ return count;
+ }
+
+-#define show_and_set_pwm(offset) \
+-static SENSOR_DEVICE_ATTR(pwm##offset, S_IWUSR | S_IRUGO, \
+- show_pwm, set_pwm, offset-1);
+-show_and_set_pwm(1)
+-show_and_set_pwm(2)
+-show_and_set_pwm(3)
++static struct sensor_device_attribute pwm[] = {
++ SENSOR_ATTR(pwm1, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 0),
++ SENSOR_ATTR(pwm2, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 1),
++ SENSOR_ATTR(pwm3, S_IWUSR | S_IRUGO, show_pwm, set_pwm, 2),
++};
+
+ static ssize_t show_in_input(struct device *dev, struct device_attribute *devattr, char *buf)
+ {
+@@ -410,26 +417,58 @@ static ssize_t set_in_max(struct device
+ return count;
+ }
+
+-#define show_and_set_in(offset) \
+-static SENSOR_DEVICE_ATTR(in##offset##_input, S_IRUGO, \
+- show_in_input, NULL, offset); \
+-static SENSOR_DEVICE_ATTR(in##offset##_min, S_IWUSR | S_IRUGO, \
+- show_in_min, set_in_min, offset); \
+-static SENSOR_DEVICE_ATTR(in##offset##_max, S_IWUSR | S_IRUGO, \
+- show_in_max, set_in_max, offset); \
+-static SENSOR_DEVICE_ATTR(in##offset##_status, S_IRUGO, \
+- show_in_status, NULL, offset);
+-show_and_set_in(0)
+-show_and_set_in(1)
+-show_and_set_in(2)
+-show_and_set_in(3)
+-show_and_set_in(4)
+-show_and_set_in(5)
+-show_and_set_in(6)
+-show_and_set_in(7)
+-show_and_set_in(8)
+-show_and_set_in(9)
+-show_and_set_in(10)
++static struct sensor_device_attribute in_input[] = {
++ SENSOR_ATTR(in0_input, S_IRUGO, show_in_input, NULL, 0),
++ SENSOR_ATTR(in1_input, S_IRUGO, show_in_input, NULL, 1),
++ SENSOR_ATTR(in2_input, S_IRUGO, show_in_input, NULL, 2),
++ SENSOR_ATTR(in3_input, S_IRUGO, show_in_input, NULL, 3),
++ SENSOR_ATTR(in4_input, S_IRUGO, show_in_input, NULL, 4),
++ SENSOR_ATTR(in5_input, S_IRUGO, show_in_input, NULL, 5),
++ SENSOR_ATTR(in6_input, S_IRUGO, show_in_input, NULL, 6),
++ SENSOR_ATTR(in7_input, S_IRUGO, show_in_input, NULL, 7),
++ SENSOR_ATTR(in8_input, S_IRUGO, show_in_input, NULL, 8),
++ SENSOR_ATTR(in9_input, S_IRUGO, show_in_input, NULL, 9),
++ SENSOR_ATTR(in10_input, S_IRUGO, show_in_input, NULL, 10),
++};
++static struct sensor_device_attribute in_status[] = {
++ SENSOR_ATTR(in0_status, S_IRUGO, show_in_status, NULL, 0),
++ SENSOR_ATTR(in1_status, S_IRUGO, show_in_status, NULL, 1),
++ SENSOR_ATTR(in2_status, S_IRUGO, show_in_status, NULL, 2),
++ SENSOR_ATTR(in3_status, S_IRUGO, show_in_status, NULL, 3),
++ SENSOR_ATTR(in4_status, S_IRUGO, show_in_status, NULL, 4),
++ SENSOR_ATTR(in5_status, S_IRUGO, show_in_status, NULL, 5),
++ SENSOR_ATTR(in6_status, S_IRUGO, show_in_status, NULL, 6),
++ SENSOR_ATTR(in7_status, S_IRUGO, show_in_status, NULL, 7),
++ SENSOR_ATTR(in8_status, S_IRUGO, show_in_status, NULL, 8),
++ SENSOR_ATTR(in9_status, S_IRUGO, show_in_status, NULL, 9),
++ SENSOR_ATTR(in10_status, S_IRUGO, show_in_status, NULL, 10),
++};
++static struct sensor_device_attribute in_min[] = {
++ SENSOR_ATTR(in0_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 0),
++ SENSOR_ATTR(in1_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 1),
++ SENSOR_ATTR(in2_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 2),
++ SENSOR_ATTR(in3_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 3),
++ SENSOR_ATTR(in4_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 4),
++ SENSOR_ATTR(in5_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 5),
++ SENSOR_ATTR(in6_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 6),
++ SENSOR_ATTR(in7_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 7),
++ SENSOR_ATTR(in8_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 8),
++ SENSOR_ATTR(in9_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 9),
++ SENSOR_ATTR(in10_min, S_IWUSR | S_IRUGO, show_in_min, set_in_min, 10),
++};
++static struct sensor_device_attribute in_max[] = {
++ SENSOR_ATTR(in0_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 0),
++ SENSOR_ATTR(in1_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 1),
++ SENSOR_ATTR(in2_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 2),
++ SENSOR_ATTR(in3_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 3),
++ SENSOR_ATTR(in4_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 4),
++ SENSOR_ATTR(in5_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 5),
++ SENSOR_ATTR(in6_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 6),
++ SENSOR_ATTR(in7_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 7),
++ SENSOR_ATTR(in8_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 8),
++ SENSOR_ATTR(in9_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 9),
++ SENSOR_ATTR(in10_max, S_IWUSR | S_IRUGO, show_in_max, set_in_max, 10),
++};
+
+ static ssize_t show_therm_input(struct device *dev, struct device_attribute *devattr, char *buf)
+ {
+@@ -511,20 +550,43 @@ static ssize_t set_therm_crit(struct dev
+ return count;
+ }
+
+-#define show_and_set_therm(offset) \
+-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+- show_therm_input, NULL, 11+offset-4); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+- show_therm_min, set_therm_min, 11+offset-4); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+- show_therm_max, set_therm_max, 11+offset-4); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+- show_therm_crit, set_therm_crit, 11+offset-4); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+- show_therm_status, NULL, 11+offset-4);
+-show_and_set_therm(4)
+-show_and_set_therm(5)
+-show_and_set_therm(6)
++/* the +11 term below reflects the fact that VLM units 11,12,13 are
++ used in the chip to measure voltage across the thermistors
++*/
++static struct sensor_device_attribute therm_input[] = {
++ SENSOR_ATTR(temp4_input, S_IRUGO, show_therm_input, NULL, 0+11),
++ SENSOR_ATTR(temp5_input, S_IRUGO, show_therm_input, NULL, 1+11),
++ SENSOR_ATTR(temp6_input, S_IRUGO, show_therm_input, NULL, 2+11),
++};
++static struct sensor_device_attribute therm_status[] = {
++ SENSOR_ATTR(temp4_status, S_IRUGO, show_therm_status, NULL, 0+11),
++ SENSOR_ATTR(temp5_status, S_IRUGO, show_therm_status, NULL, 1+11),
++ SENSOR_ATTR(temp6_status, S_IRUGO, show_therm_status, NULL, 2+11),
++};
++static struct sensor_device_attribute therm_min[] = {
++ SENSOR_ATTR(temp4_min, S_IRUGO | S_IWUSR,
++ show_therm_min, set_therm_min, 0+11),
++ SENSOR_ATTR(temp5_min, S_IRUGO | S_IWUSR,
++ show_therm_min, set_therm_min, 1+11),
++ SENSOR_ATTR(temp6_min, S_IRUGO | S_IWUSR,
++ show_therm_min, set_therm_min, 2+11),
++};
++static struct sensor_device_attribute therm_max[] = {
++ SENSOR_ATTR(temp4_max, S_IRUGO | S_IWUSR,
++ show_therm_max, set_therm_max, 0+11),
++ SENSOR_ATTR(temp5_max, S_IRUGO | S_IWUSR,
++ show_therm_max, set_therm_max, 1+11),
++ SENSOR_ATTR(temp6_max, S_IRUGO | S_IWUSR,
++ show_therm_max, set_therm_max, 2+11),
++};
++static struct sensor_device_attribute therm_crit[] = {
++ SENSOR_ATTR(temp4_crit, S_IRUGO | S_IWUSR,
++ show_therm_crit, set_therm_crit, 0+11),
++ SENSOR_ATTR(temp5_crit, S_IRUGO | S_IWUSR,
++ show_therm_crit, set_therm_crit, 1+11),
++ SENSOR_ATTR(temp6_crit, S_IRUGO | S_IWUSR,
++ show_therm_crit, set_therm_crit, 2+11),
++};
+
+ static ssize_t show_vid(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+@@ -630,20 +692,40 @@ static ssize_t set_temp_crit(struct devi
+ return count;
+ }
+
+-#define show_and_set_temp(offset) \
+-static SENSOR_DEVICE_ATTR(temp##offset##_input, S_IRUGO, \
+- show_temp_input, NULL, offset-1); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_min, S_IWUSR | S_IRUGO, \
+- show_temp_min, set_temp_min, offset-1); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_max, S_IWUSR | S_IRUGO, \
+- show_temp_max, set_temp_max, offset-1); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_crit, S_IWUSR | S_IRUGO, \
+- show_temp_crit, set_temp_crit, offset-1); \
+-static SENSOR_DEVICE_ATTR(temp##offset##_status, S_IRUGO, \
+- show_temp_status, NULL, offset-1);
+-show_and_set_temp(1)
+-show_and_set_temp(2)
+-show_and_set_temp(3)
++static struct sensor_device_attribute temp_input[] = {
++ SENSOR_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL, 0),
++ SENSOR_ATTR(temp2_input, S_IRUGO, show_temp_input, NULL, 1),
++ SENSOR_ATTR(temp3_input, S_IRUGO, show_temp_input, NULL, 2),
++};
++static struct sensor_device_attribute temp_status[] = {
++ SENSOR_ATTR(temp1_status, S_IRUGO, show_temp_status, NULL, 0),
++ SENSOR_ATTR(temp2_status, S_IRUGO, show_temp_status, NULL, 1),
++ SENSOR_ATTR(temp3_status, S_IRUGO, show_temp_status, NULL, 2),
++};
++static struct sensor_device_attribute temp_min[] = {
++ SENSOR_ATTR(temp1_min, S_IRUGO | S_IWUSR,
++ show_temp_min, set_temp_min, 0),
++ SENSOR_ATTR(temp2_min, S_IRUGO | S_IWUSR,
++ show_temp_min, set_temp_min, 1),
++ SENSOR_ATTR(temp3_min, S_IRUGO | S_IWUSR,
++ show_temp_min, set_temp_min, 2),
++};
++static struct sensor_device_attribute temp_max[] = {
++ SENSOR_ATTR(temp1_max, S_IRUGO | S_IWUSR,
++ show_temp_max, set_temp_max, 0),
++ SENSOR_ATTR(temp2_max, S_IRUGO | S_IWUSR,
++ show_temp_max, set_temp_max, 1),
++ SENSOR_ATTR(temp3_max, S_IRUGO | S_IWUSR,
++ show_temp_max, set_temp_max, 2),
++};
++static struct sensor_device_attribute temp_crit[] = {
++ SENSOR_ATTR(temp1_crit, S_IRUGO | S_IWUSR,
++ show_temp_crit, set_temp_crit, 0),
++ SENSOR_ATTR(temp2_crit, S_IRUGO | S_IWUSR,
++ show_temp_crit, set_temp_crit, 1),
++ SENSOR_ATTR(temp3_crit, S_IRUGO | S_IWUSR,
++ show_temp_crit, set_temp_crit, 2),
++};
+
+ static ssize_t show_temp_alarms(struct device *dev, struct device_attribute *attr, char *buf)
+ {
+@@ -749,22 +831,24 @@ static int __init pc87360_find(int sioad
+ static int pc87360_detect(struct i2c_adapter *adapter)
+ {
+ int i;
+- struct i2c_client *new_client;
++ struct i2c_client *client;
+ struct pc87360_data *data;
+ int err = 0;
+ const char *name = "pc87360";
+ int use_thermistors = 0;
++ struct device *dev;
+
+ if (!(data = kzalloc(sizeof(struct pc87360_data), GFP_KERNEL)))
+ return -ENOMEM;
+
+- new_client = &data->client;
+- i2c_set_clientdata(new_client, data);
+- new_client->addr = address;
++ client = &data->client;
++ dev = &client->dev;
++ i2c_set_clientdata(client, data);
++ client->addr = address;
+ init_MUTEX(&data->lock);
+- new_client->adapter = adapter;
+- new_client->driver = &pc87360_driver;
+- new_client->flags = 0;
++ client->adapter = adapter;
++ client->driver = &pc87360_driver;
++ client->flags = 0;
+
+ data->fannr = 2;
+ data->innr = 0;
+@@ -792,7 +876,7 @@ static int pc87360_detect(struct i2c_ada
+ break;
+ }
+
+- strcpy(new_client->name, name);
++ strlcpy(client->name, name, sizeof(client->name));
+ data->valid = 0;
+ init_MUTEX(&data->update_lock);
+
+@@ -800,7 +884,7 @@ static int pc87360_detect(struct i2c_ada
+ if (((data->address[i] = extra_isa[i]))
+ && !request_region(extra_isa[i], PC87360_EXTENT,
+ pc87360_driver.driver.name)) {
+- dev_err(&new_client->dev, "Region 0x%x-0x%x already "
++ dev_err(&client->dev, "Region 0x%x-0x%x already "
+ "in use!\n", extra_isa[i],
+ extra_isa[i]+PC87360_EXTENT-1);
+ for (i--; i >= 0; i--)
+@@ -814,7 +898,7 @@ static int pc87360_detect(struct i2c_ada
+ if (data->fannr)
+ data->fan_conf = confreg[0] | (confreg[1] << 8);
+
+- if ((err = i2c_attach_client(new_client)))
++ if ((err = i2c_attach_client(client)))
+ goto ERROR2;
+
+ /* Use the correct reference voltage
+@@ -828,7 +912,7 @@ static int pc87360_detect(struct i2c_ada
+ PC87365_REG_TEMP_CONFIG);
+ }
+ data->in_vref = (i&0x02) ? 3025 : 2966;
+- dev_dbg(&new_client->dev, "Using %s reference voltage\n",
++ dev_dbg(&client->dev, "Using %s reference voltage\n",
+ (i&0x02) ? "external" : "internal");
+
+ data->vid_conf = confreg[3];
+@@ -847,154 +931,64 @@ static int pc87360_detect(struct i2c_ada
+ if (devid == 0xe9 && data->address[1]) /* PC87366 */
+ use_thermistors = confreg[2] & 0x40;
+
+- pc87360_init_client(new_client, use_thermistors);
++ pc87360_init_client(client, use_thermistors);
+ }
+
+ /* Register sysfs hooks */
+- 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 ERROR3;
+ }
+
+ if (data->innr) {
+- device_create_file(&new_client->dev, &sensor_dev_attr_in0_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in1_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in2_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in3_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in4_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in5_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in6_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in7_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in8_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in9_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in10_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in0_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in1_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in2_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in3_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in4_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in5_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in6_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in7_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in8_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in9_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in10_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in0_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in1_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in2_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in3_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in4_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in5_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in6_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in7_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in8_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in9_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in10_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in0_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in1_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in2_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in3_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in4_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in5_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in6_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in7_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in8_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in9_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_in10_status.dev_attr);
+-
+- device_create_file(&new_client->dev, &dev_attr_cpu0_vid);
+- device_create_file(&new_client->dev, &dev_attr_vrm);
+- device_create_file(&new_client->dev, &dev_attr_alarms_in);
++ for (i = 0; i < 11; i++) {
++ device_create_file(dev, &in_input[i].dev_attr);
++ device_create_file(dev, &in_min[i].dev_attr);
++ device_create_file(dev, &in_max[i].dev_attr);
++ device_create_file(dev, &in_status[i].dev_attr);
++ }
++ device_create_file(dev, &dev_attr_cpu0_vid);
++ device_create_file(dev, &dev_attr_vrm);
++ device_create_file(dev, &dev_attr_alarms_in);
+ }
+
+ if (data->tempnr) {
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_crit.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_crit.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp1_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp2_status.dev_attr);
+-
+- device_create_file(&new_client->dev, &dev_attr_alarms_temp);
+- }
+- if (data->tempnr == 3) {
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_crit.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp3_status.dev_attr);
++ for (i = 0; i < data->tempnr; i++) {
++ device_create_file(dev, &temp_input[i].dev_attr);
++ device_create_file(dev, &temp_min[i].dev_attr);
++ device_create_file(dev, &temp_max[i].dev_attr);
++ device_create_file(dev, &temp_crit[i].dev_attr);
++ device_create_file(dev, &temp_status[i].dev_attr);
++ }
++ device_create_file(dev, &dev_attr_alarms_temp);
+ }
++
+ if (data->innr == 14) {
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_input.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_min.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_max.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_crit.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_crit.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_crit.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp4_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp5_status.dev_attr);
+- device_create_file(&new_client->dev, &sensor_dev_attr_temp6_status.dev_attr);
+- }
+-
+- if (data->fannr) {
+- if (FAN_CONFIG_MONITOR(data->fan_conf, 0)) {
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan1_input.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan1_min.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan1_div.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan1_status.dev_attr);
+- }
+-
+- if (FAN_CONFIG_MONITOR(data->fan_conf, 1)) {
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan2_input.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan2_min.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan2_div.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan2_status.dev_attr);
+- }
+-
+- if (FAN_CONFIG_CONTROL(data->fan_conf, 0))
+- device_create_file(&new_client->dev, &sensor_dev_attr_pwm1.dev_attr);
+- if (FAN_CONFIG_CONTROL(data->fan_conf, 1))
+- device_create_file(&new_client->dev, &sensor_dev_attr_pwm2.dev_attr);
+- }
+- if (data->fannr == 3) {
+- if (FAN_CONFIG_MONITOR(data->fan_conf, 2)) {
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan3_input.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan3_min.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan3_div.dev_attr);
+- device_create_file(&new_client->dev,
+- &sensor_dev_attr_fan3_status.dev_attr);
++ for (i = 0; i < 3; i++) {
++ device_create_file(dev, &therm_input[i].dev_attr);
++ device_create_file(dev, &therm_min[i].dev_attr);
++ device_create_file(dev, &therm_max[i].dev_attr);
++ device_create_file(dev, &therm_crit[i].dev_attr);
++ device_create_file(dev, &therm_status[i].dev_attr);
+ }
++ }
+
+- if (FAN_CONFIG_CONTROL(data->fan_conf, 2))
+- device_create_file(&new_client->dev, &sensor_dev_attr_pwm3.dev_attr);
++ for (i = 0; i < data->fannr; i++) {
++ if (FAN_CONFIG_MONITOR(data->fan_conf, i)) {
++ device_create_file(dev, &fan_input[i].dev_attr);
++ device_create_file(dev, &fan_min[i].dev_attr);
++ device_create_file(dev, &fan_div[i].dev_attr);
++ device_create_file(dev, &fan_status[i].dev_attr);
++ }
++ if (FAN_CONFIG_CONTROL(data->fan_conf, i))
++ device_create_file(dev, &pwm[i].dev_attr);
+ }
+
+ return 0;
+
+ ERROR3:
+- i2c_detach_client(new_client);
++ i2c_detach_client(client);
+ ERROR2:
+ for (i = 0; i < 3; i++) {
+ if (data->address[i]) {
+@@ -1071,7 +1065,7 @@ static void pc87360_init_client(struct i
+ }
+
+ nr = data->innr < 11 ? data->innr : 11;
+- for (i=0; i<nr; i++) {
++ for (i = 0; i < nr; i++) {
+ if (init >= init_in[i]) {
+ /* Forcibly enable voltage channel */
+ reg = pc87360_read_value(data, LD_IN, i,
+@@ -1088,14 +1082,14 @@ static void pc87360_init_client(struct i
+
+ /* We can't blindly trust the Super-I/O space configuration bit,
+ most BIOS won't set it properly */
+- for (i=11; i<data->innr; i++) {
++ for (i = 11; i < data->innr; i++) {
+ reg = pc87360_read_value(data, LD_IN, i,
+ PC87365_REG_TEMP_STATUS);
+ use_thermistors = use_thermistors || (reg & 0x01);
+ }
+
+ i = use_thermistors ? 2 : 0;
+- for (; i<data->tempnr; i++) {
++ for (; i < data->tempnr; i++) {
+ if (init >= init_temp[i]) {
+ /* Forcibly enable temperature channel */
+ reg = pc87360_read_value(data, LD_TEMP, i,
+@@ -1111,7 +1105,7 @@ static void pc87360_init_client(struct i
+ }
+
+ if (use_thermistors) {
+- for (i=11; i<data->innr; i++) {
++ for (i = 11; i < data->innr; i++) {
+ if (init >= init_in[i]) {
+ /* The pin may already be used by thermal
+ diodes */
diff --git a/i2c/hwmon-w83792d-inline-register-access-functions.patch b/i2c/hwmon-w83792d-inline-register-access-functions.patch
new file mode 100644
index 0000000000000..73b124f47f0e0
--- /dev/null
+++ b/i2c/hwmon-w83792d-inline-register-access-functions.patch
@@ -0,0 +1,72 @@
+From khali@linux-fr.org Mon Jan 9 14:10:38 2006
+Date: Mon, 9 Jan 2006 23:07:05 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Yuan Mu <Ymu@winbond.com.tw>
+Subject: hwmon: Inline w83792d register access functions
+Message-Id: <20060109230705.457c0960.khali@linux-fr.org>
+Content-Disposition: inline; filename=hwmon-w83792d-inline-register-access-functions.patch
+
+Inline w83792d_{read,write}_value for better performance.
+
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Acked-by: Yuan Mu <Ymu@winbond.com.tw>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/hwmon/w83792d.c | 31 ++++++++++++++-----------------
+ 1 file changed, 14 insertions(+), 17 deletions(-)
+
+--- gregkh-2.6.orig/drivers/hwmon/w83792d.c
++++ gregkh-2.6/drivers/hwmon/w83792d.c
+@@ -303,10 +303,6 @@ struct w83792d_data {
+ static int w83792d_attach_adapter(struct i2c_adapter *adapter);
+ static int w83792d_detect(struct i2c_adapter *adapter, int address, int kind);
+ static int w83792d_detach_client(struct i2c_client *client);
+-
+-static int w83792d_read_value(struct i2c_client *client, u8 register);
+-static int w83792d_write_value(struct i2c_client *client, u8 register,
+- u8 value);
+ static struct w83792d_data *w83792d_update_device(struct device *dev);
+
+ #ifdef DEBUG
+@@ -329,6 +325,20 @@ static inline long in_count_from_reg(int
+ return ((data->in[nr] << 2) | ((data->low_bits >> (2 * nr)) & 0x03));
+ }
+
++/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
++ but the driver only accesses registers in bank 0, so we don't have
++ to switch banks and lock access between switches. */
++static inline int w83792d_read_value(struct i2c_client *client, u8 reg)
++{
++ return i2c_smbus_read_byte_data(client, reg);
++}
++
++static inline int
++w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
++{
++ return i2c_smbus_write_byte_data(client, reg, value);
++}
++
+ /* following are the sysfs callback functions */
+ static ssize_t show_in(struct device *dev, struct device_attribute *attr,
+ char *buf)
+@@ -1386,19 +1396,6 @@ w83792d_detach_client(struct i2c_client
+ return 0;
+ }
+
+-/* The SMBus locks itself. The Winbond W83792D chip has a bank register,
+- but the driver only accesses registers in bank 0, so we don't have
+- to switch banks and lock access between switches. */
+-static int w83792d_read_value(struct i2c_client *client, u8 reg)
+-{
+- return i2c_smbus_read_byte_data(client, reg);
+-}
+-
+-static int w83792d_write_value(struct i2c_client *client, u8 reg, u8 value)
+-{
+- return i2c_smbus_write_byte_data(client, reg, value);
+-}
+-
+ static void
+ w83792d_init_client(struct i2c_client *client)
+ {
diff --git a/i2c/i2c-algo-sibyte-module-param.patch b/i2c/i2c-algo-sibyte-module-param.patch
new file mode 100644
index 0000000000000..ffc8f65fa438f
--- /dev/null
+++ b/i2c/i2c-algo-sibyte-module-param.patch
@@ -0,0 +1,32 @@
+From khali@linux-fr.org Mon Jan 9 14:10:43 2006
+Date: Mon, 9 Jan 2006 23:09:57 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Eric Sesterhenn <snakebyte@gmx.de>
+Subject: i2c: Use module_param in i2c-algo-sibyte
+Message-Id: <20060109230957.041f41af.khali@linux-fr.org>
+Content-Disposition: inline; filename=i2c-algo-sibyte-module-param.patch
+
+From: Eric Sesterhenn <snakebyte@gmx.de>
+
+this patch changes MODULE_PARM usage
+to module_param in i2c-algo-sibyte.c
+
+Signed-off-by: Eric Sesterhenn <snakebyte@gmx.de>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/i2c/algos/i2c-algo-sibyte.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- gregkh-2.6.orig/drivers/i2c/algos/i2c-algo-sibyte.c
++++ gregkh-2.6/drivers/i2c/algos/i2c-algo-sibyte.c
+@@ -202,7 +202,7 @@ EXPORT_SYMBOL(i2c_sibyte_del_bus);
+ #ifdef MODULE
+ MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
+ MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
+-MODULE_PARM(bit_scan, "i");
++module_param(bit_scan, int, 0);
+ MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+ MODULE_LICENSE("GPL");
+
diff --git a/i2c/i2c-busses-use-array-size-macro.patch b/i2c/i2c-busses-use-array-size-macro.patch
new file mode 100644
index 0000000000000..1597f735e48b6
--- /dev/null
+++ b/i2c/i2c-busses-use-array-size-macro.patch
@@ -0,0 +1,82 @@
+From khali@linux-fr.org Mon Jan 9 14:22:08 2006
+Date: Mon, 9 Jan 2006 23:19:51 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Tobias Klauser <tklauser@nuerscht.ch>
+Subject: i2c: Use ARRAY_SIZE macro
+Message-Id: <20060109231951.2b9634ff.khali@linux-fr.org>
+Content-Disposition: inline; filename=i2c-busses-use-array-size-macro.patch
+
+From: Tobias Klauser <tklauser@nuerscht.ch>
+
+Use ARRAY_SIZE macro instead of sizeof(x)/sizeof(x[0]). Some trailing
+whitespaces are also removed.
+
+Signed-off-by: Tobias Klauser <tklauser@nuerscht.ch>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Cc: Russell King <rmk+kernel@arm.linux.org.uk>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ drivers/i2c/busses/i2c-parport-light.c | 9 +++------
+ drivers/i2c/busses/i2c-parport.c | 7 ++-----
+ drivers/i2c/busses/i2c-pxa.c | 2 +-
+ 3 files changed, 6 insertions(+), 12 deletions(-)
+
+--- gregkh-2.6.orig/drivers/i2c/busses/i2c-parport.c
++++ gregkh-2.6/drivers/i2c/busses/i2c-parport.c
+@@ -241,14 +241,11 @@ static struct parport_driver i2c_parport
+
+ static int __init i2c_parport_init(void)
+ {
+- int type_count;
+-
+- type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
+- if (type < 0 || type >= type_count) {
++ if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
+ type = 0;
+ }
+-
++
+ return parport_register_driver(&i2c_parport_driver);
+ }
+
+--- gregkh-2.6.orig/drivers/i2c/busses/i2c-parport-light.c
++++ gregkh-2.6/drivers/i2c/busses/i2c-parport-light.c
+@@ -121,14 +121,11 @@ static struct i2c_adapter parport_adapte
+
+ static int __init i2c_parport_init(void)
+ {
+- int type_count;
+-
+- type_count = sizeof(adapter_parm)/sizeof(struct adapter_parm);
+- if (type < 0 || type >= type_count) {
++ if (type < 0 || type >= ARRAY_SIZE(adapter_parm)) {
+ printk(KERN_WARNING "i2c-parport: invalid type (%d)\n", type);
+ type = 0;
+ }
+-
++
+ if (base == 0) {
+ printk(KERN_INFO "i2c-parport: using default base 0x%x\n", DEFAULT_BASE);
+ base = DEFAULT_BASE;
+@@ -152,7 +149,7 @@ static int __init i2c_parport_init(void)
+ release_region(base, 3);
+ return -ENODEV;
+ }
+-
++
+ return 0;
+ }
+
+--- gregkh-2.6.orig/drivers/i2c/busses/i2c-pxa.c
++++ gregkh-2.6/drivers/i2c/busses/i2c-pxa.c
+@@ -861,7 +861,7 @@ static irqreturn_t i2c_pxa_handler(int t
+ decode_ISR(isr);
+ }
+
+- if (i2c->irqlogidx < sizeof(i2c->isrlog)/sizeof(u32))
++ if (i2c->irqlogidx < ARRAY_SIZE(i2c->isrlog))
+ i2c->isrlog[i2c->irqlogidx++] = isr;
+
+ show_state(i2c);
diff --git a/i2c/i2c-sis96x-rename-documentation.patch b/i2c/i2c-sis96x-rename-documentation.patch
new file mode 100644
index 0000000000000..315fdfb7bfc40
--- /dev/null
+++ b/i2c/i2c-sis96x-rename-documentation.patch
@@ -0,0 +1,174 @@
+From khali@linux-fr.org Mon Jan 9 13:49:56 2006
+Date: Mon, 9 Jan 2006 22:46:14 +0100
+From: Jean Delvare <khali@linux-fr.org>
+To: Greg KH <greg@kroah.com>
+Cc: Rudolf Marek <r.marek@sh.cvut.cz>
+Subject: i2c: Rename i2c-sis96x documentation file
+Message-Id: <20060109224614.4d55d8a2.khali@linux-fr.org>
+Content-Disposition: inline; filename=i2c-sis96x-rename-documentation.patch
+
+From: Rudolf Marek <r.marek@sh.cvut.cz>
+
+This patch just renames the documentation file to correct file name.
+i2c-sis69x -> i2c-sis96x.
+
+Signed-off-by: Rudolf Marek <r.marek@sh.cvut.cz>
+Signed-off-by: Jean Delvare <khali@linux-fr.org>
+Signed-off-by: Greg Kroah-Hartman <gregkh@suse.de>
+---
+ Documentation/i2c/busses/i2c-sis69x | 73 ------------------------------------
+ Documentation/i2c/busses/i2c-sis96x | 73 ++++++++++++++++++++++++++++++++++++
+ 2 files changed, 73 insertions(+), 73 deletions(-)
+
+--- gregkh-2.6.orig/Documentation/i2c/busses/i2c-sis69x
++++ /dev/null
+@@ -1,73 +0,0 @@
+-Kernel driver i2c-sis96x
+-
+-Replaces 2.4.x i2c-sis645
+-
+-Supported adapters:
+- * Silicon Integrated Systems Corp (SiS)
+- Any combination of these host bridges:
+- 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
+- and these south bridges:
+- 961, 962, 963(L)
+-
+-Author: Mark M. Hoffman <mhoffman@lightlink.com>
+-
+-Description
+------------
+-
+-This SMBus only driver is known to work on motherboards with the above
+-named chipset combinations. The driver was developed without benefit of a
+-proper datasheet from SiS. The SMBus registers are assumed compatible with
+-those of the SiS630, although they are located in a completely different
+-place. Thanks to Alexander Malysh <amalysh@web.de> for providing the
+-SiS630 datasheet (and driver).
+-
+-The command "lspci" as root should produce something like these lines:
+-
+-00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
+-00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
+-00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
+-
+-or perhaps this...
+-
+-00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
+-00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
+-00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
+-
+-(kernel versions later than 2.4.18 may fill in the "Unknown"s)
+-
+-If you cant see it please look on quirk_sis_96x_smbus
+-(drivers/pci/quirks.c) (also if southbridge detection fails)
+-
+-I suspect that this driver could be made to work for the following SiS
+-chipsets as well: 635, and 635T. If anyone owns a board with those chips
+-AND is willing to risk crashing & burning an otherwise well-behaved kernel
+-in the name of progress... please contact me at <mhoffman@lightlink.com> or
+-via the project's mailing list: <lm-sensors@lm-sensors.org>. Please
+-send bug reports and/or success stories as well.
+-
+-
+-TO DOs
+-------
+-
+-* The driver does not support SMBus block reads/writes; I may add them if a
+-scenario is found where they're needed.
+-
+-
+-Thank You
+----------
+-
+-Mark D. Studebaker <mdsxyz123@yahoo.com>
+- - design hints and bug fixes
+-Alexander Maylsh <amalysh@web.de>
+- - ditto, plus an important datasheet... almost the one I really wanted
+-Hans-Günter Lütke Uphues <hg_lu@t-online.de>
+- - patch for SiS735
+-Robert Zwerus <arzie@dds.nl>
+- - testing for SiS645DX
+-Kianusch Sayah Karadji <kianusch@sk-tech.net>
+- - patch for SiS645DX/962
+-Ken Healy
+- - patch for SiS655
+-
+-To anyone else who has written w/ feedback, thanks!
+-
+--- /dev/null
++++ gregkh-2.6/Documentation/i2c/busses/i2c-sis96x
+@@ -0,0 +1,73 @@
++Kernel driver i2c-sis96x
++
++Replaces 2.4.x i2c-sis645
++
++Supported adapters:
++ * Silicon Integrated Systems Corp (SiS)
++ Any combination of these host bridges:
++ 645, 645DX (aka 646), 648, 650, 651, 655, 735, 745, 746
++ and these south bridges:
++ 961, 962, 963(L)
++
++Author: Mark M. Hoffman <mhoffman@lightlink.com>
++
++Description
++-----------
++
++This SMBus only driver is known to work on motherboards with the above
++named chipset combinations. The driver was developed without benefit of a
++proper datasheet from SiS. The SMBus registers are assumed compatible with
++those of the SiS630, although they are located in a completely different
++place. Thanks to Alexander Malysh <amalysh@web.de> for providing the
++SiS630 datasheet (and driver).
++
++The command "lspci" as root should produce something like these lines:
++
++00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
++00:02.0 ISA bridge: Silicon Integrated Systems [SiS] 85C503/5513
++00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
++
++or perhaps this...
++
++00:00.0 Host bridge: Silicon Integrated Systems [SiS]: Unknown device 0645
++00:02.0 ISA bridge: Silicon Integrated Systems [SiS]: Unknown device 0961
++00:02.1 SMBus: Silicon Integrated Systems [SiS]: Unknown device 0016
++
++(kernel versions later than 2.4.18 may fill in the "Unknown"s)
++
++If you cant see it please look on quirk_sis_96x_smbus
++(drivers/pci/quirks.c) (also if southbridge detection fails)
++
++I suspect that this driver could be made to work for the following SiS
++chipsets as well: 635, and 635T. If anyone owns a board with those chips
++AND is willing to risk crashing & burning an otherwise well-behaved kernel
++in the name of progress... please contact me at <mhoffman@lightlink.com> or
++via the project's mailing list: <lm-sensors@lm-sensors.org>. Please
++send bug reports and/or success stories as well.
++
++
++TO DOs
++------
++
++* The driver does not support SMBus block reads/writes; I may add them if a
++scenario is found where they're needed.
++
++
++Thank You
++---------
++
++Mark D. Studebaker <mdsxyz123@yahoo.com>
++ - design hints and bug fixes
++Alexander Maylsh <amalysh@web.de>
++ - ditto, plus an important datasheet... almost the one I really wanted
++Hans-Günter Lütke Uphues <hg_lu@t-online.de>
++ - patch for SiS735
++Robert Zwerus <arzie@dds.nl>
++ - testing for SiS645DX
++Kianusch Sayah Karadji <kianusch@sk-tech.net>
++ - patch for SiS645DX/962
++Ken Healy
++ - patch for SiS655
++
++To anyone else who has written w/ feedback, thanks!
++