--- linux-2.6.21.old/drivers/hwmon/adm1021.c	2007-04-26 05:08:32.000000000 +0200
+++ linux-2.6.21/drivers/hwmon/adm1021.c	2007-07-08 09:48:47.000000000 +0200
@@ -1,6 +1,6 @@
 /*
     adm1021.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
+		monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
     Philip Edelbrock <phil@netroedge.com>
 
@@ -25,6 +25,7 @@
 #include <linux/jiffies.h>
 #include <linux/i2c.h>
 #include <linux/hwmon.h>
+#include <linux/hwmon-sysfs.h>
 #include <linux/err.h>
 #include <linux/mutex.h>
 
@@ -32,11 +33,12 @@
 /* Addresses to scan */
 static unsigned short normal_i2c[] = { 0x18, 0x19, 0x1a,
 					0x29, 0x2a, 0x2b,
-					0x4c, 0x4d, 0x4e, 
+					0x4c, 0x4d, 0x4e,
 					I2C_CLIENT_END };
 
 /* Insmod parameters */
-I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm, mc1066);
+I2C_CLIENT_INSMOD_8(adm1021, adm1023, max1617, max1617a, thmc10, lm84, gl523sm,
+			mc1066);
 
 /* adm1021 constants specified below */
 
@@ -45,8 +47,10 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, ma
 #define ADM1021_REG_TEMP		0x00
 #define ADM1021_REG_REMOTE_TEMP		0x01
 #define ADM1021_REG_STATUS		0x02
-#define ADM1021_REG_MAN_ID		0x0FE	/* 0x41 = AMD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi*/
-#define ADM1021_REG_DEV_ID		0x0FF	/* ADM1021 = 0x0X, ADM1023 = 0x3X */
+/* 0x41 = AD, 0x49 = TI, 0x4D = Maxim, 0x23 = Genesys , 0x54 = Onsemi */
+#define ADM1021_REG_MAN_ID		0x0FE
+/* ADM1021 = 0x0X, ADM1023 = 0x3X */
+#define ADM1021_REG_DEV_ID		0x0FF
 #define ADM1021_REG_DIE_CODE		0x0FF	/* MAX1617A */
 /* These use different addresses for reading/writing */
 #define ADM1021_REG_CONFIG_R		0x03
@@ -54,11 +58,11 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, ma
 #define ADM1021_REG_CONV_RATE_R		0x04
 #define ADM1021_REG_CONV_RATE_W		0x0A
 /* These are for the ADM1023's additional precision on the remote temp sensor */
-#define ADM1021_REG_REM_TEMP_PREC	0x010
-#define ADM1021_REG_REM_OFFSET		0x011
-#define ADM1021_REG_REM_OFFSET_PREC	0x012
-#define ADM1021_REG_REM_TOS_PREC	0x013
-#define ADM1021_REG_REM_THYST_PREC	0x014
+#define ADM1023_REG_REM_TEMP_PREC	0x010
+#define ADM1023_REG_REM_OFFSET		0x011
+#define ADM1023_REG_REM_OFFSET_PREC	0x012
+#define ADM1023_REG_REM_TOS_PREC	0x013
+#define ADM1023_REG_REM_THYST_PREC	0x014
 /* limits */
 #define ADM1021_REG_TOS_R		0x05
 #define ADM1021_REG_TOS_W		0x0B
@@ -71,20 +75,11 @@ I2C_CLIENT_INSMOD_8(adm1021, adm1023, ma
 /* write-only */
 #define ADM1021_REG_ONESHOT		0x0F
 
-
-/* Conversions. Rounding and limit checking is only done on the TO_REG
-   variants. Note that you should be a bit careful with which arguments
-   these macros are called: arguments may be evaluated more than once.
-   Fixing this is just not worth it. */
-/* Conversions  note: 1021 uses normal integer signed-byte format*/
-#define TEMP_FROM_REG(val)	(val > 127 ? (val-256)*1000 : val*1000)
-#define TEMP_TO_REG(val)	(SENSORS_LIMIT((val < 0 ? (val/1000)+256 : val/1000),0,255))
-
 /* Initial values */
 
-/* Note: Even though I left the low and high limits named os and hyst, 
-they don't quite work like a thermostat the way the LM75 does.  I.e., 
-a lower temp than THYST actually triggers an alarm instead of 
+/* Note: Even though I left the low and high limits named os and hyst,
+they don't quite work like a thermostat the way the LM75 does.  I.e.,
+a lower temp than THYST actually triggers an alarm instead of
 clearing it.  Weird, ey?   --Phil  */
 
 /* Each client has this additional data */
@@ -97,28 +92,22 @@ struct adm1021_data {
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
 
-	u8	temp_max;	/* Register values */
-	u8	temp_hyst;
-	u8	temp_input;
-	u8	remote_temp_max;
-	u8	remote_temp_hyst;
-	u8	remote_temp_input;
-	u8	alarms;
-        /* Special values for ADM1023 only */
-	u8	remote_temp_prec;
-	u8	remote_temp_os_prec;
-	u8	remote_temp_hyst_prec;
-	u8	remote_temp_offset;
-	u8	remote_temp_offset_prec;
+	s8 temp_max[2];		/* Register values */
+	s8 temp_min[2];
+	s8 temp[2];
+	u8 alarms;
+	/* Special values for ADM1023 only */
+	u8 remote_temp_prec;
+	u8 remote_temp_os_prec;
+	u8 remote_temp_hyst_prec;
+	u8 remote_temp_offset;
+	u8 remote_temp_offset_prec;
 };
 
 static int adm1021_attach_adapter(struct i2c_adapter *adapter);
 static int adm1021_detect(struct i2c_adapter *adapter, int address, int kind);
 static void adm1021_init_client(struct i2c_client *client);
 static int adm1021_detach_client(struct i2c_client *client);
-static int adm1021_read_value(struct i2c_client *client, u8 reg);
-static int adm1021_write_value(struct i2c_client *client, u8 reg,
-			       u16 value);
 static struct adm1021_data *adm1021_update_device(struct device *dev);
 
 /* (amalysh) read only mode, otherwise any limit's writing confuse BIOS */
@@ -135,53 +124,89 @@ static struct i2c_driver adm1021_driver 
 	.detach_client	= adm1021_detach_client,
 };
 
-#define show(value)	\
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
-{									\
-	struct adm1021_data *data = adm1021_update_device(dev);		\
-	return sprintf(buf, "%d\n", TEMP_FROM_REG(data->value));	\
+static ssize_t show_temp(struct device *dev,
+			 struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct adm1021_data *data = adm1021_update_device(dev);
+
+	return sprintf(buf, "%d\n", 1000 * data->temp[index]);
+}
+
+static ssize_t show_temp_max(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct adm1021_data *data = adm1021_update_device(dev);
+
+	return sprintf(buf, "%d\n", 1000 * data->temp_max[index]);
+}
+
+static ssize_t show_temp_min(struct device *dev,
+			     struct device_attribute *devattr, char *buf)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct adm1021_data *data = adm1021_update_device(dev);
+
+	return sprintf(buf, "%d\n", 1000 * data->temp_min[index]);
 }
-show(temp_max);
-show(temp_hyst);
-show(temp_input);
-show(remote_temp_max);
-show(remote_temp_hyst);
-show(remote_temp_input);
 
 #define show2(value)	\
-static ssize_t show_##value(struct device *dev, struct device_attribute *attr, char *buf)		\
+static ssize_t show_##value(struct device *dev,				\
+			    struct device_attribute *attr,		\
+			    char *buf)					\
 {									\
 	struct adm1021_data *data = adm1021_update_device(dev);		\
 	return sprintf(buf, "%d\n", data->value);			\
 }
 show2(alarms);
 
-#define set(value, reg)	\
-static ssize_t set_##value(struct device *dev, struct device_attribute *attr, const char *buf, size_t count)	\
-{								\
-	struct i2c_client *client = to_i2c_client(dev);		\
-	struct adm1021_data *data = i2c_get_clientdata(client);	\
-	int temp = simple_strtoul(buf, NULL, 10);		\
-								\
-	mutex_lock(&data->update_lock);				\
-	data->value = TEMP_TO_REG(temp);			\
-	adm1021_write_value(client, reg, data->value);		\
-	mutex_unlock(&data->update_lock);			\
-	return count;						\
-}
-set(temp_max, ADM1021_REG_TOS_W);
-set(temp_hyst, ADM1021_REG_THYST_W);
-set(remote_temp_max, ADM1021_REG_REMOTE_TOS_W);
-set(remote_temp_hyst, ADM1021_REG_REMOTE_THYST_W);
-
-static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max, set_temp_max);
-static DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_hyst, set_temp_hyst);
-static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input, NULL);
-static DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_remote_temp_max, set_remote_temp_max);
-static DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_remote_temp_hyst, set_remote_temp_hyst);
-static DEVICE_ATTR(temp2_input, S_IRUGO, show_remote_temp_input, NULL);
-static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
+static ssize_t set_temp_max(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1021_data *data = i2c_get_clientdata(client);
+	int temp = simple_strtol(buf, NULL, 10) / 1000;
 
+	mutex_lock(&data->update_lock);
+	data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127);
+	i2c_smbus_write_byte_data(client, ADM1021_REG_TOS_W + 2 * index, temp);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static ssize_t set_temp_min(struct device *dev,
+			    struct device_attribute *devattr,
+			    const char *buf, size_t count)
+{
+	int index = to_sensor_dev_attr(devattr)->index;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct adm1021_data *data = i2c_get_clientdata(client);
+	int temp = simple_strtol(buf, NULL, 10) / 1000;
+
+	mutex_lock(&data->update_lock);
+	data->temp_max[index] = SENSORS_LIMIT(temp, -128, 127);
+	i2c_smbus_write_byte_data(client,
+				  ADM1021_REG_THYST_W + 2 * index, temp);
+	mutex_unlock(&data->update_lock);
+
+	return count;
+}
+
+static SENSOR_DEVICE_ATTR(temp1_input, S_IRUGO, show_temp, NULL, 0);
+static SENSOR_DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_max,
+			  set_temp_max, 0);
+static SENSOR_DEVICE_ATTR(temp1_min, S_IWUSR | S_IRUGO, show_temp_min,
+			  set_temp_min, 0);
+static SENSOR_DEVICE_ATTR(temp2_input, S_IRUGO, show_temp, NULL, 1);
+static SENSOR_DEVICE_ATTR(temp2_max, S_IWUSR | S_IRUGO, show_temp_max,
+			  set_temp_max, 1);
+static SENSOR_DEVICE_ATTR(temp2_min, S_IWUSR | S_IRUGO, show_temp_min,
+			  set_temp_min, 1);
+static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 static int adm1021_attach_adapter(struct i2c_adapter *adapter)
 {
@@ -191,12 +216,12 @@ static int adm1021_attach_adapter(struct
 }
 
 static struct attribute *adm1021_attributes[] = {
-	&dev_attr_temp1_max.attr,
-	&dev_attr_temp1_min.attr,
-	&dev_attr_temp1_input.attr,
-	&dev_attr_temp2_max.attr,
-	&dev_attr_temp2_min.attr,
-	&dev_attr_temp2_input.attr,
+	&sensor_dev_attr_temp1_max.dev_attr.attr,
+	&sensor_dev_attr_temp1_min.dev_attr.attr,
+	&sensor_dev_attr_temp1_input.dev_attr.attr,
+	&sensor_dev_attr_temp2_max.dev_attr.attr,
+	&sensor_dev_attr_temp2_min.dev_attr.attr,
+	&sensor_dev_attr_temp2_input.dev_attr.attr,
 	&dev_attr_alarms.attr,
 	NULL
 };
@@ -212,15 +237,20 @@ static int adm1021_detect(struct i2c_ada
 	struct adm1021_data *data;
 	int err = 0;
 	const char *type_name = "";
+	int conv_rate, status, config;
 
-	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA)) {
+		pr_debug("adm1021: detect failed, "
+			 "smbus byte data not supported!\n");
 		goto error0;
+	}
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access adm1021_{read,write}_value. */
 
 	if (!(data = kzalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
+		pr_debug("adm1021: detect failed, kzalloc failed!\n");
 		err = -ENOMEM;
 		goto error0;
 	}
@@ -230,13 +260,17 @@ static int adm1021_detect(struct i2c_ada
 	new_client->addr = address;
 	new_client->adapter = adapter;
 	new_client->driver = &adm1021_driver;
-	new_client->flags = 0;
+	status = i2c_smbus_read_byte_data(new_client, ADM1021_REG_STATUS);
+	conv_rate = i2c_smbus_read_byte_data(new_client,
+					     ADM1021_REG_CONV_RATE_R);
+	config = i2c_smbus_read_byte_data(new_client, ADM1021_REG_CONFIG_R);
 
 	/* Now, we do the remaining detection. */
 	if (kind < 0) {
-		if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00
-		 || (adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x3F) != 0x00
-		 || (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) & 0xF8) != 0x00) {
+		if ((status & 0x03) != 0x00 || (config & 0x3F) != 0x00
+		    || (conv_rate & 0xF8) != 0x00) {
+			pr_debug("adm1021: detect failed, "
+				 "chip not detected!\n");
 			err = -ENODEV;
 			goto error1;
 		}
@@ -244,9 +278,10 @@ static int adm1021_detect(struct i2c_ada
 
 	/* Determine the chip type. */
 	if (kind <= 0) {
-		i = adm1021_read_value(new_client, ADM1021_REG_MAN_ID);
+		i = i2c_smbus_read_byte_data(new_client, ADM1021_REG_MAN_ID);
 		if (i == 0x41)
-			if ((adm1021_read_value(new_client, ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
+			if ((i2c_smbus_read_byte_data(new_client,
+					ADM1021_REG_DEV_ID) & 0x0F0) == 0x030)
 				kind = adm1023;
 			else
 				kind = adm1021;
@@ -255,15 +290,16 @@ static int adm1021_detect(struct i2c_ada
 		else if (i == 0x23)
 			kind = gl523sm;
 		else if ((i == 0x4d) &&
-			 (adm1021_read_value(new_client, ADM1021_REG_DEV_ID) == 0x01))
+			 (i2c_smbus_read_byte_data(new_client,
+						   ADM1021_REG_DEV_ID) == 0x01))
 			kind = max1617a;
 		else if (i == 0x54)
 			kind = mc1066;
 		/* LM84 Mfr ID in a different place, and it has more unused bits */
-		else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00
-		      && (kind == 0 /* skip extra detection */
-		       || ((adm1021_read_value(new_client, ADM1021_REG_CONFIG_R) & 0x7F) == 0x00
-			&& (adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0xAB) == 0x00)))
+		else if (conv_rate == 0x00
+			 && (kind == 0 /* skip extra detection */
+			     || ((config & 0x7F) == 0x00
+				 && (status & 0xAB) == 0x00)))
 			kind = lm84;
 		else
 			kind = max1617;
@@ -286,11 +322,12 @@ static int adm1021_detect(struct i2c_ada
 	} else if (kind == mc1066) {
 		type_name = "mc1066";
 	}
+	pr_debug("adm1021: Detected chip %s at adapter %d, address 0x%02x.\n",
+		 type_name, i2c_adapter_id(adapter), address);
 
-	/* Fill in the remaining client fields and put it into the global list */
+	/* Fill in the remaining client fields */
 	strlcpy(new_client->name, type_name, I2C_NAME_SIZE);
 	data->type = kind;
-	data->valid = 0;
 	mutex_init(&data->update_lock);
 
 	/* Tell the I2C layer a new client has arrived */
@@ -326,10 +363,10 @@ error0:
 static void adm1021_init_client(struct i2c_client *client)
 {
 	/* Enable ADC and disable suspend mode */
-	adm1021_write_value(client, ADM1021_REG_CONFIG_W,
-		adm1021_read_value(client, ADM1021_REG_CONFIG_R) & 0xBF);
+	i2c_smbus_write_byte_data(client, ADM1021_REG_CONFIG_W,
+		i2c_smbus_read_byte_data(client, ADM1021_REG_CONFIG_R) & 0xBF);
 	/* Set Conversion rate to 1/sec (this can be tinkered with) */
-	adm1021_write_value(client, ADM1021_REG_CONV_RATE_W, 0x04);
+	i2c_smbus_write_byte_data(client, ADM1021_REG_CONV_RATE_W, 0x04);
 }
 
 static int adm1021_detach_client(struct i2c_client *client)
@@ -347,19 +384,6 @@ static int adm1021_detach_client(struct 
 	return 0;
 }
 
-/* All registers are byte-sized */
-static int adm1021_read_value(struct i2c_client *client, u8 reg)
-{
-	return i2c_smbus_read_byte_data(client, reg);
-}
-
-static int adm1021_write_value(struct i2c_client *client, u8 reg, u16 value)
-{
-	if (!read_only)
-		return i2c_smbus_write_byte_data(client, reg, value);
-	return 0;
-}
-
 static struct adm1021_data *adm1021_update_device(struct device *dev)
 {
 	struct i2c_client *client = to_i2c_client(dev);
@@ -369,21 +393,39 @@ static struct adm1021_data *adm1021_upda
 
 	if (time_after(jiffies, data->last_updated + HZ + HZ / 2)
 	    || !data->valid) {
+		int i;
+
 		dev_dbg(&client->dev, "Starting adm1021 update\n");
 
-		data->temp_input = adm1021_read_value(client, ADM1021_REG_TEMP);
-		data->temp_max = adm1021_read_value(client, ADM1021_REG_TOS_R);
-		data->temp_hyst = adm1021_read_value(client, ADM1021_REG_THYST_R);
-		data->remote_temp_input = adm1021_read_value(client, ADM1021_REG_REMOTE_TEMP);
-		data->remote_temp_max = adm1021_read_value(client, ADM1021_REG_REMOTE_TOS_R);
-		data->remote_temp_hyst = adm1021_read_value(client, ADM1021_REG_REMOTE_THYST_R);
-		data->alarms = adm1021_read_value(client, ADM1021_REG_STATUS) & 0x7c;
+		for (i = 0; i < 2; i++) {
+			data->temp[i] = i2c_smbus_read_byte_data(client,
+						ADM1021_REG_TEMP + i);
+			data->temp_max[i] =
+				i2c_smbus_read_byte_data(client,
+						ADM1021_REG_TOS_R + 2 * i);
+			data->temp_min[i] =
+				i2c_smbus_read_byte_data(client,
+						ADM1021_REG_THYST_R + 2 * i);
+		}
+		data->alarms =
+			i2c_smbus_read_byte_data(client,
+						ADM1021_REG_STATUS) & 0x7c;
 		if (data->type == adm1023) {
-			data->remote_temp_prec = adm1021_read_value(client, ADM1021_REG_REM_TEMP_PREC);
-			data->remote_temp_os_prec = adm1021_read_value(client, ADM1021_REG_REM_TOS_PREC);
-			data->remote_temp_hyst_prec = adm1021_read_value(client, ADM1021_REG_REM_THYST_PREC);
-			data->remote_temp_offset = adm1021_read_value(client, ADM1021_REG_REM_OFFSET);
-			data->remote_temp_offset_prec = adm1021_read_value(client, ADM1021_REG_REM_OFFSET_PREC);
+			data->remote_temp_prec =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_TEMP_PREC);
+			data->remote_temp_os_prec =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_TOS_PREC);
+			data->remote_temp_hyst_prec =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_THYST_PREC);
+			data->remote_temp_offset =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_OFFSET);
+			data->remote_temp_offset_prec =
+				i2c_smbus_read_byte_data(client,
+						ADM1023_REG_REM_OFFSET_PREC);
 		}
 		data->last_updated = jiffies;
 		data->valid = 1;
