Skip to contentSkip to conversation

I2C update for 2.6.5

PATCH New Greg KH 1 participant 31 messages Apr 14, 2004

Subsystems (5)
lore
Share & tools
lore

Greg KH

author
#0 lore raw

PATCH 1/1 I2C update for 2.6.5

Hi,

Here are some i2c driver patches 2.6.5. They have all been in the -mm kernels for a number of weeks now and do the following:
- add a new bus i2c driver
- add 2 new chip drivers
- updated documentation
- lots of bug fixes

Please pull from: bk://linuxusb.bkbits.net/i2c-2.6

Individual patches will follow, sent to the sensors and linux-kernel lists.

thanks,

greg k-h

 arch/i386/pci/irq.c               |   10 
 Documentation/i2c/porting-clients |   46 ++--
 Documentation/i2c/sysfs-interface |   78 +++---
 drivers/i2c/busses/i2c-ali1563.c  |  429 +++++++++++++++++++++++++++++++++++++-
 drivers/i2c/busses/Kconfig        |   28 +-
 drivers/i2c/busses/Makefile       |    3 
 drivers/i2c/chips/adm1021.c       |   54 +---
 drivers/i2c/chips/asb100.c        |   38 +--
 drivers/i2c/chips/ds1621.c        |   28 --
 drivers/i2c/chips/eeprom.c        |   16 -
 drivers/i2c/chips/fscher.c        |   19 -
 drivers/i2c/chips/gl518sm.c       |   24 --
 drivers/i2c/chips/it87.c          |   51 ++--
 drivers/i2c/chips/Kconfig         |   23 +-
 drivers/i2c/chips/lm75.c          |   24 --
 drivers/i2c/chips/lm78.c          |   20 +
 drivers/i2c/chips/lm80.c          |   72 ++++--
 drivers/i2c/chips/lm83.c          |   17 -
 drivers/i2c/chips/lm85.c          |   14 -
 drivers/i2c/chips/lm90.c          |   17 -
 drivers/i2c/chips/Makefile        |    2 
 drivers/i2c/chips/pcf8574.c       |  260 ++++++++++++++++++++++-
 drivers/i2c/chips/pcf8591.c       |  349 +++++++++++++++++++++++++++++-
 drivers/i2c/chips/via686a.c       |  109 +--------
 drivers/i2c/chips/w83627hf.c      |   69 +++---
 drivers/i2c/chips/w83781d.c       |  201 +++++------------
 drivers/i2c/chips/w83l785ts.c     |   18 -
 include/linux/pci_ids.h           |    2 
 28 files changed, 1444 insertions(+), 577 deletions(-)

-----

<aurelien:aurel32.net>:
o I2C: New chip driver: pcf8591
o I2C: add new chip driver: pcf8574

<mochel:digitalimplant.org>:
o I2C: class fixup for the ali1563 driver
o I2C: Fix check for DEBUG in i2c-ali1563
o I2C: Add ALi 1563 i2c driver
o I2C: Add support for the ALi 1563 in the PCI IRQ routing code
o I2C: Add ALi 1563 Device ID to pci_ids.h

Andrew Morton:
o I2C: i2c-ali1563.c section fix

Greg Kroah-Hartman:
o I2C: clean up out of order bus Makefile and Kconfig entries
o I2C: minor bugfixes for the pcf8591.c driver and formatting cleanups

Jean Delvare:
o I2C: Fix voltage rounding in asb100
o I2C: No reset not limit init in via686a
o I2C: Fix voltage rounding in lm80
o I2C: make I2C chip drivers return -EINVAL on error
o I2C: pwm support in w83781d.c
o I2C: Error paths in it87 and via686a drivers
o I2C: Rework memory allocation in i2c chip drivers
o I2C: Enable changing fan_divs in lm80 driver
o I2C: Refactor swap_bytes in i2c chip drivers
o I2C: Discard pointless comment in via686a
o I2C: Incorrect memset in eeprom.c
o I2C: i2c documentation update (2/2)
o I2C: i2c documentation update (1/2)
o I2C: Prevent misdetections in adm1021 driver
o I2C: Setting w83627hf fan_div preserves fan_min
o I2C: adm1021 (probably) does something VERY,VERY BAD
o I2C: initialize fan_mins in w83781d, asb100 and lm78
o I2C: Discard out-of-date comment in adm1021 driver
o I2C: w83781d fan_div code refactoring

Mark M. Hoffman:
o I2C: fix asb100 bug

author
#1 lore raw

PATCH 1/1 I2C update for 2.6.5

ChangeSet 1.1643.36.1, 2004/03/19 13:24:14-08:00, [email protected]

[PATCH] I2C: w83781d fan_div code refactoring

Quoting myself:

Quoted 3 lines

This tends to increase the size of the three set_store_regs_fan_div functions, and I am considering refactoring them at some point. Later though.

Here is the promised refactoring. Tested on my AS99127F rev.1, seems to work. As for the previous patch, there is a part that I cannot test with the AS99127F, so additional testing is welcome.

I agree this makes the code slightly less readable, but this saves 60 lines of code (1754 bytes, around 3% of the driver total), and is actually far less complex that I first feared.

 drivers/i2c/chips/w83781d.c |   94 +++++++-------------------------------------
 1 files changed, 17 insertions(+), 77 deletions(-)
drivers/i2c/chips/w83781d.c +17 -77
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
@@ -620,7 +620,7 @@
    least suprise; the user doesn't expect the fan minimum to change just
    because the divisor changed. */
 static ssize_t
-store_regs_fan_div_1(struct device *dev, const char *buf, size_t count)
+store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83781d_data *data = i2c_get_clientdata(client);
@@ -628,92 +628,28 @@
 	u8 reg;
 
 	/* Save fan_min */
-	min = FAN_FROM_REG(data->fan_min[0],
-			   DIV_FROM_REG(data->fan_div[0]));
+	min = FAN_FROM_REG(data->fan_min[nr],
+			   DIV_FROM_REG(data->fan_div[nr]));
 
-	data->fan_div[0] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
+	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
 				      data->type);
 
-	reg = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0xcf;
-	reg |= (data->fan_div[0] & 0x03) << 4;
-	w83781d_write_value(client, W83781D_REG_VID_FANDIV, reg);
+	reg = (w83781d_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
+	       & (nr==0 ? 0xcf : 0x3f))
+	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
+	w83781d_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
 
 	/* w83781d and as99127f don't have extended divisor bits */
 	if (data->type != w83781d && data->type != as99127f) {
-		reg = w83781d_read_value(client, W83781D_REG_VBAT) & 0xdf;
-		reg |= (data->fan_div[0] & 0x04) << 3;
+		reg = (w83781d_read_value(client, W83781D_REG_VBAT)
+		       & ~(1 << (5 + nr)))
+		    | ((data->fan_div[nr] & 0x04) << (3 + nr));
 		w83781d_write_value(client, W83781D_REG_VBAT, reg);
 	}
 
 	/* Restore fan_min */
-	data->fan_min[0] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[0]));
-	w83781d_write_value(client, W83781D_REG_FAN_MIN(1), data->fan_min[0]);
-
-	return count;
-}
-
-static ssize_t
-store_regs_fan_div_2(struct device *dev, const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83781d_data *data = i2c_get_clientdata(client);
-	unsigned long min;
-	u8 reg;
-
-	/* Save fan_min */
-	min = FAN_FROM_REG(data->fan_min[1],
-			   DIV_FROM_REG(data->fan_div[1]));
-
-	data->fan_div[1] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
-				      data->type);
-
-	reg = w83781d_read_value(client, W83781D_REG_VID_FANDIV) & 0x3f;
-	reg |= (data->fan_div[1] & 0x03) << 6;
-	w83781d_write_value(client, W83781D_REG_VID_FANDIV, reg);
-
-	/* w83781d and as99127f don't have extended divisor bits */
-	if (data->type != w83781d && data->type != as99127f) {
-		reg = w83781d_read_value(client, W83781D_REG_VBAT) & 0xbf;
-		reg |= (data->fan_div[1] & 0x04) << 4;
-		w83781d_write_value(client, W83781D_REG_VBAT, reg);
-	}
-
-	/* Restore fan_min */
-	data->fan_min[1] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[1]));
-	w83781d_write_value(client, W83781D_REG_FAN_MIN(2), data->fan_min[1]);
-
-	return count;
-}
-
-static ssize_t
-store_regs_fan_div_3(struct device *dev, const char *buf, size_t count)
-{
-	struct i2c_client *client = to_i2c_client(dev);
-	struct w83781d_data *data = i2c_get_clientdata(client);
-	unsigned long min;
-	u8 reg;
-
-	/* Save fan_min */
-	min = FAN_FROM_REG(data->fan_min[2],
-			   DIV_FROM_REG(data->fan_div[2]));
-
-	data->fan_div[2] = DIV_TO_REG(simple_strtoul(buf, NULL, 10),
-				      data->type);
-
-	reg = w83781d_read_value(client, W83781D_REG_PIN) & 0x3f;
-	reg |= (data->fan_div[2] & 0x03) << 6;
-	w83781d_write_value(client, W83781D_REG_PIN, reg);
-
-	/* w83781d and as99127f don't have extended divisor bits */
-	if (data->type != w83781d && data->type != as99127f) {
-		reg = w83781d_read_value(client, W83781D_REG_VBAT) & 0x7f;
-		reg |= (data->fan_div[2] & 0x04) << 5;
-		w83781d_write_value(client, W83781D_REG_VBAT, reg);
-	}
-
-	/* Restore fan_min */
-	data->fan_min[2] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[2]));
-	w83781d_write_value(client, W83781D_REG_FAN_MIN(3), data->fan_min[2]);
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	w83781d_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 
 	return count;
 }
@@ -722,6 +658,10 @@
 static ssize_t show_regs_fan_div_##offset (struct device *dev, char *buf) \
 { \
 	return show_fan_div_reg(dev, buf, offset); \
+} \
+static ssize_t store_regs_fan_div_##offset (struct device *dev, const char *buf, size_t count) \
+{ \
+	return store_fan_div_reg(dev, buf, count, offset - 1); \
 } \
 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, show_regs_fan_div_##offset, store_regs_fan_div_##offset)
 
author
#2 lore raw

ChangeSet 1.1643.36.2, 2004/03/19 13:24:39-08:00, [email protected]

[PATCH] I2C: add new chip driver: pcf8574

Please find below a patch against kernel 2.6.5-rc1 to add the pcf8574 driver (an I/O expander for the I2C bus). I have ported it from the 2.4 version, and it includes some fixes and simplifications.

It has been reviewed by Jean Delvare on IRC.

 drivers/i2c/chips/Kconfig   |   11 +
 drivers/i2c/chips/Makefile  |    1 
 drivers/i2c/chips/pcf8574.c |  245 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 257 insertions(+)
drivers/i2c/chips/Kconfig +11 -0
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
@@ -209,4 +209,15 @@
 	  This driver can also be built as a module.  If so, the module
 	  will be called eeprom.
 
+config SENSORS_PCF8574
+	tristate "Philips PCF8574 and PCF8574A"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for Philips PCF8574 and 
+	  PCF8574A chips.
+
+	  This driver can also be built as a module. If so, the module
+	  will be called pcf8574.
+
 endmenu
drivers/i2c/chips/Makefile +1 -0
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
@@ -19,6 +19,7 @@
 obj-$(CONFIG_SENSORS_LM83)	+= lm83.o
 obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
+obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 
drivers/i2c/chips/pcf8574.c new file +245 -0

245 lines not on this page · raw message

author
#3 lore raw

ChangeSet 1.1643.36.3, 2004/03/25 10:50:47-08:00, [email protected]

[PATCH] I2C: Discard out-of-date comment in adm1021 driver

This simple patch discards an out-of-date comment in the adm1021 driver. I've done the same in our CVS repository where many more drivers were affected.

I agree it's not very important, but I prefer it to be done before any driver with the error is used as a base to port a new driver, and the misinformation spreads.

 drivers/i2c/chips/adm1021.c |    3 ---
 1 files changed, 3 deletions(-)
drivers/i2c/chips/adm1021.c +0 -3
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
@@ -151,9 +151,6 @@
 	.detach_client	= adm1021_detach_client,
 };
 
-/* I choose here for semi-static allocation. Complete dynamic
-   allocation could also be used; the code needed for this would probably
-   take more memory than the datastructure takes now. */
 static int adm1021_id = 0;
 
 #define show(value)	\
author
#4 lore raw

ChangeSet 1.1643.36.4, 2004/03/25 10:51:45-08:00, [email protected]

[PATCH] I2C: initialize fan_mins in w83781d, asb100 and lm78

Quoting myself:

Quoted 4 lines

While testing, I found a corner case that isn't handled properly. It doesn't seem to be handled by the lm78 and the asb100 either. Setting fanN_div before ever reading from the chip or setting fanN_min will make use of fanN_min while it was never initialized.

The following patch addesses the issue. Tested to work on my AS99127F rev.1 (which means that only the changes to the w83781d driver were actually tested). Testers welcome.

 drivers/i2c/chips/asb100.c  |    5 +++++
 drivers/i2c/chips/lm78.c    |    6 ++++++
 drivers/i2c/chips/w83781d.c |    6 ++++++
 3 files changed, 17 insertions(+)
drivers/i2c/chips/asb100.c +5 -0
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
@@ -807,6 +807,11 @@
 	/* Initialize the chip */
 	asb100_init_client(new_client);
 
+	/* A few vars need to be filled upon startup */
+	data->fan_min[0] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(0));
+	data->fan_min[1] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(1));
+	data->fan_min[2] = asb100_read_value(new_client, ASB100_REG_FAN_MIN(2));
+
 	/* Register sysfs hooks */
 	device_create_file_in(new_client, 0);
 	device_create_file_in(new_client, 1);
drivers/i2c/chips/lm78.c +6 -0
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
@@ -625,6 +625,12 @@
 	/* Initialize the LM78 chip */
 	lm78_init_client(new_client);
 
+	/* A few vars need to be filled upon startup */
+	for (i = 0; i < 3; i++) {
+		data->fan_min[i] = lm78_read_value(new_client,
+					LM78_REG_FAN_MIN(i));
+	}
+
 	/* Register sysfs hooks */
 	device_create_file(&new_client->dev, &dev_attr_in0_input);
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
drivers/i2c/chips/w83781d.c +6 -0
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
@@ -1252,6 +1252,12 @@
 	/* Initialize the chip */
 	w83781d_init_client(new_client);
 
+	/* A few vars need to be filled upon startup */
+	for (i = 1; i <= 3; i++) {
+		data->fan_min[i - 1] = w83781d_read_value(new_client,
+					W83781D_REG_FAN_MIN(i));
+	}
+
 	/* Register sysfs hooks */
 	device_create_file_in(new_client, 0);
 	if (kind != w83783s && kind != w83697hf)
author
#5 lore raw

ChangeSet 1.1643.36.5, 2004/03/26 13:52:39-08:00, [email protected]

[PATCH] I2C: adm1021 (probably) does something VERY,VERY BAD

Quoting myself:

Quoted 2 lines

3* Drop adm1021's limit init. This was already done in the 2.4 driver and should have been done in 2.6 as well.

Here is a patch that does that. It also prevents bit 7 (and unused bits) of configuration register from being reset, as was discussed before:
http://archives.andrew.net.au/lm-sensors/msg04593.html
That second part needs to be backported to the 2.4 driver, and I will do so.

Additionally, we get rid of a useless label.

The patch is untested (I don't own any supported chip) but quite straightforward IMHO.

 drivers/i2c/chips/adm1021.c |   19 +++----------------
 1 files changed, 3 insertions(+), 16 deletions(-)
drivers/i2c/chips/adm1021.c +3 -16
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
@@ -98,10 +98,6 @@
 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  */
-#define adm1021_INIT_TOS		60
-#define adm1021_INIT_THYST		20
-#define adm1021_INIT_REMOTE_TOS		60
-#define adm1021_INIT_REMOTE_THYST	20
 
 /* Each client has this additional data */
 struct adm1021_data {
@@ -306,7 +302,7 @@
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
-		goto error3;
+		goto error1;
 
 	/* Initialize the ADM1021 chip */
 	adm1021_init_client(new_client);
@@ -324,7 +320,6 @@
 
 	return 0;
 
-error3:
 error1:
 	kfree(new_client);
 error0:
@@ -333,17 +328,9 @@
 
 static void adm1021_init_client(struct i2c_client *client)
 {
-	/* Initialize the adm1021 chip */
-	adm1021_write_value(client, ADM1021_REG_TOS_W,
-			    adm1021_INIT_TOS);
-	adm1021_write_value(client, ADM1021_REG_THYST_W,
-			    adm1021_INIT_THYST);
-	adm1021_write_value(client, ADM1021_REG_REMOTE_TOS_W,
-			    adm1021_INIT_REMOTE_TOS);
-	adm1021_write_value(client, ADM1021_REG_REMOTE_THYST_W,
-			    adm1021_INIT_REMOTE_THYST);
 	/* Enable ADC and disable suspend mode */
-	adm1021_write_value(client, ADM1021_REG_CONFIG_W, 0);
+	adm1021_write_value(client, ADM1021_REG_CONFIG_W,
+		adm1021_read_value(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);
 }
author
#6 lore raw

ChangeSet 1.1643.36.6, 2004/03/26 13:53:01-08:00, [email protected]

[PATCH] I2C: Setting w83627hf fan_div preserves fan_min

Here is a patch that updates the w83627hf driver in the exact same way I did recently for the w83781d driver. There were two problems:
1* Fan divisor storing code was ugly, badly ripped from the 2.4 w83627hf
driver and/or the 2.6 w83781d driver.
2* Setting fan divisors wouldn't preserve fan mins.

Exactly the same as w83781d:
http://archives.andrew.net.au/lm-sensors/msg06952.html
http://archives.andrew.net.au/lm-sensors/msg07008.html

No surprise since the w83627hf driver is a fork of the w83781d driver.

Since the two drivers are strongly similar, I took the code directly from the updated w83781d driver. I cannot test the w83627hf driver (testers welcome BTW) but this makes me feel confident that the code is correct.

To make it clear, this single patch is the w83627f equivalent of the three patches I submitted for the w83781d:
* Cleanup
* Refactoring
* Setting fan_div preserves fan_min
All in one (much better looking BTW).

 drivers/i2c/chips/w83627hf.c |   54 ++++++++++++++++++++++++-------------------
 1 files changed, 31 insertions(+), 23 deletions(-)
drivers/i2c/chips/w83627hf.c +31 -23
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
@@ -659,34 +659,37 @@
 		       (long) DIV_FROM_REG(data->fan_div[nr - 1]));
 }
 
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
 static ssize_t
 store_fan_div_reg(struct device *dev, const char *buf, size_t count, int nr)
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83627hf_data *data = i2c_get_clientdata(client);
-	u32 val, old, old2, old3 = 0;
+	unsigned long min;
+	u8 reg;
 
-	val = simple_strtoul(buf, NULL, 10);
-	old = w83627hf_read_value(client, W83781D_REG_VID_FANDIV);
-	old3 = w83627hf_read_value(client, W83781D_REG_VBAT);
-	data->fan_div[nr - 1] = DIV_TO_REG(val);
-
-	if (nr >= 3 && data->type != w83697hf) {
-		old2 = w83627hf_read_value(client, W83781D_REG_PIN);
-		old2 = (old2 & 0x3f) | ((data->fan_div[2] & 0x03) << 6);
-		w83627hf_write_value(client, W83781D_REG_PIN, old2);
-		old3 = (old3 & 0x7f) | ((data->fan_div[2] & 0x04) << 5);
-	}
-	if (nr >= 2) {
-		old = (old & 0x3f) | ((data->fan_div[1] & 0x03) << 6);
-		old3 = (old3 & 0xbf) | ((data->fan_div[1] & 0x04) << 4);
-	}
-	if (nr >= 1) {
-		old = (old & 0xcf) | ((data->fan_div[0] & 0x03) << 4);
-		w83627hf_write_value(client, W83781D_REG_VID_FANDIV, old);
-		old3 = (old3 & 0xdf) | ((data->fan_div[0] & 0x04) << 3);
-		w83627hf_write_value(client, W83781D_REG_VBAT, old3);
-	}
+	/* Save fan_min */
+	min = FAN_FROM_REG(data->fan_min[nr],
+			   DIV_FROM_REG(data->fan_div[nr]));
+
+	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+	reg = (w83627hf_read_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV)
+	       & (nr==0 ? 0xcf : 0x3f))
+	    | ((data->fan_div[nr] & 0x03) << (nr==0 ? 4 : 6));
+	w83627hf_write_value(client, nr==2 ? W83781D_REG_PIN : W83781D_REG_VID_FANDIV, reg);
+
+	reg = (w83627hf_read_value(client, W83781D_REG_VBAT)
+	       & ~(1 << (5 + nr)))
+	    | ((data->fan_div[nr] & 0x04) << (3 + nr));
+	w83627hf_write_value(client, W83781D_REG_VBAT, reg);
+
+	/* Restore fan_min */
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	w83627hf_write_value(client, W83781D_REG_FAN_MIN(nr+1), data->fan_min[nr]);
 
 	return count;
 }
@@ -700,7 +703,7 @@
 store_regs_fan_div_##offset (struct device *dev, \
 			    const char *buf, size_t count) \
 { \
-	return store_fan_div_reg(dev, buf, count, offset); \
+	return store_fan_div_reg(dev, buf, count, offset - 1); \
 } \
 static DEVICE_ATTR(fan##offset##_div, S_IRUGO | S_IWUSR, \
 		  show_regs_fan_div_##offset, store_regs_fan_div_##offset)
@@ -981,6 +984,11 @@
 
 	/* Initialize the chip */
 	w83627hf_init_client(new_client);
+
+	/* A few vars need to be filled upon startup */
+	data->fan_min[0] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(1));
+	data->fan_min[1] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(2));
+	data->fan_min[2] = w83627hf_read_value(new_client, W83781D_REG_FAN_MIN(3));
 
 	/* Register sysfs hooks */
 	device_create_file_in(new_client, 0);
author
#7 lore raw

ChangeSet 1.1643.36.7, 2004/03/30 14:26:19-08:00, [email protected]

[PATCH] I2C: Prevent misdetections in adm1021 driver

Yet another patch for the adm1021 chip driver. I refined the detection code a bit in order to prevent chip misdetection. Some chips handled by the adm1021 driver are hard to detect and identify (LM84 and MAX1617) so we tend to accept any chip it the valid I2C address range as one of these. It has caused much, much trouble already. See these threads for example:

http://archives.andrew.net.au/lm-sensors/msg04448.html
http://archives.andrew.net.au/lm-sensors/msg04624.html
http://archives.andrew.net.au/lm-sensors/msg05560.html
http://archives.andrew.net.au/lm-sensors/msg05871.html
http://archives.andrew.net.au/lm-sensors/msg06754.html
http://archives.andrew.net.au/lm-sensors/msg07181.html

And this ticket:

http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket=1434

So I thought it would be good to prevent this kind of problems if possible, and read the 8 datasheets again in search for ways to refine the detection method.

I changed it in sensors-detect already, and had positive feedback from one user. I will also backport the changes to the driver to the 2.4 version we have in CVS.

What the patch does:

* Use unused bits of two more registers (configuration and conversion rate) to reduce misdetections.

* Return with -ENODEV if the detection fails.

* Change the order in which we try to identify the chips. We better finish with the LM84 and the MAX1617, in this order, because they are harder to identify and are more likely to result in false positives.

* Refine LM84 detection. The LM84 has less features than the other chips(chip cannot be stopped, conversion rate cannot be set, no low limits) so it has extra unused bits.

* Do not intialize the chip if it was detected as an LM84. This one cannot be stopped so why would we try to start it again? And as said right before, conversion rate isn't changeable either.

Note that I couldn't test the changes on any supported chip since I don't own any. Still I believe that they should be applied, since the current code already broke one system and seriously harmed several others. I believe it's not critical if it turns out that we reject valid chips (which shouldn't happen if the datasheets are correct, anyway). People will simply let us know and we'll be less restrictive. In the meantime they can force the driver. That said, testers are welcome, as usual.

 drivers/i2c/chips/adm1021.c |   18 +++++++++++++-----
 1 files changed, 13 insertions(+), 5 deletions(-)
drivers/i2c/chips/adm1021.c +13 -5
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
@@ -246,8 +246,12 @@
 
 	/* Now, we do the remaining detection. */
 	if (kind < 0) {
-		if ((adm1021_read_value(new_client, ADM1021_REG_STATUS) & 0x03) != 0x00)
+		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) {
+			err = -ENODEV;
 			goto error1;
+		}
 	}
 
 	/* Determine the chip type. */
@@ -265,11 +269,14 @@
 		else if ((i == 0x4d) &&
 			 (adm1021_read_value(new_client, ADM1021_REG_DEV_ID) == 0x01))
 			kind = max1617a;
-		/* LM84 Mfr ID in a different place */
-		else if (adm1021_read_value(new_client, ADM1021_REG_CONV_RATE_R) == 0x00)
-			kind = lm84;
 		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)))
+			kind = lm84;
 		else
 			kind = max1617;
 	}
@@ -305,7 +312,8 @@
 		goto error1;
 
 	/* Initialize the ADM1021 chip */
-	adm1021_init_client(new_client);
+	if (kind != lm84)
+		adm1021_init_client(new_client);
 
 	/* Register sysfs hooks */
 	device_create_file(&new_client->dev, &dev_attr_temp1_max);
author
#8 lore raw

ChangeSet 1.1643.36.8, 2004/03/30 14:26:38-08:00, [email protected]

[PATCH] I2C: i2c documentation update (1/2)

Here is an update to my 2.4 to 2.6 i2c client porting guide. The changes were inspired by the feedback I got with the drivers that have been ported so far.

 Documentation/i2c/porting-clients |   46 +++++++++++++++++++++++---------------
 1 files changed, 29 insertions(+), 17 deletions(-)
Documentation/i2c/porting-clients +29 -17
diff -Nru a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
@@ -1,4 +1,4 @@
-Revision 3, 2003-10-04
+Revision 4, 2004-03-30
 Jean Delvare <[email protected]>
 Greg KH <[email protected]>
 
@@ -24,9 +24,10 @@
   #include <linux/slab.h>
   #include <linux/i2c.h>
   #include <linux/i2c-sensor.h>
-  #include <linux/i2c-vid.h>     /* if you need VRM support */
-  #include <asm/io.h>            /* if you have I/O operations */
-  Some extra headers may be required for a given driver.
+  #include <linux/i2c-vid.h>	/* if you need VRM support */
+  #include <asm/io.h>		/* if you have I/O operations */
+  Please respect this inclusion order. Some extra headers may be
+  required for a given driver (e.g. "lm75.h").
 
 * [Addresses] SENSORS_I2C_END becomes I2C_CLIENT_END, SENSORS_ISA_END
   becomes I2C_CLIENT_ISA_END.
@@ -37,9 +38,9 @@
   names for sysfs files (see the Sysctl section below).
 
 * [Function prototypes] The detect functions loses its flags
-  parameter. Sysctl (e.g. lm75_temp) and miscellaneous (e.g.
-  swap_bytes) functions are off the list of prototypes. This
-  usually leaves five prototypes:
+  parameter. Sysctl (e.g. lm75_temp) and miscellaneous functions
+  are off the list of prototypes. This usually leaves five
+  prototypes:
   static int lm75_attach_adapter(struct i2c_adapter *adapter);
   static int lm75_detect(struct i2c_adapter *adapter, int address,
       int kind);
@@ -70,13 +71,14 @@
 * [Detect] As mentioned earlier, the flags parameter is gone.
   The type_name and client_name strings are replaced by a single
   name string, which will be filled with a lowercase, short string
-  (typically the driver name, e.g. "lm75"). The errorN labels are
-  reduced to the number needed. If that number is 2 (i2c-only
-  drivers), it is advised that the labels are named exit and
-  exit_free. For i2c+isa drivers, labels should be named ERROR0,
-  ERROR1 and ERROR2. Don't forget to properly set err before
-  jumping to error labels. By the way, labels should be
-  left-aligned.
+  (typically the driver name, e.g. "lm75").
+  In i2c-only drivers, drop the i2c_is_isa_adapter check, it's
+  useless.
+  The errorN labels are reduced to the number needed. If that number
+  is 2 (i2c-only drivers), it is advised that the labels are named
+  exit and exit_free. For i2c+isa drivers, labels should be named
+  ERROR0, ERROR1 and ERROR2. Don't forget to properly set err before
+  jumping to error labels. By the way, labels should be left-aligned.
   Use memset to fill the client and data area with 0x00.
   Use i2c_set_clientdata to set the client data (as opposed to
   a direct access to client->data).
@@ -85,6 +87,11 @@
   device_create_file. Move the driver initialization before any
   sysfs file creation.
 
+* [Init] Limits must not be set by the driver (can be done later in
+  user-space). Chip should not be reset default (although a module
+  parameter may be used to force is), and initialization should be
+  limited to the strictly necessary steps.
+
 * [Detach] Get rid of data, remove the call to
   i2c_deregister_entry.
 
@@ -92,7 +99,8 @@
   i2c_get_clientdata(client) instead.
 
 * [Interface] Init function should not print anything. Make sure
-  there is a MODULE_LICENSE() line.
+  there is a MODULE_LICENSE() line, at the bottom of the file
+  (after MODULE_AUTHOR() and MODULE_DESCRIPTION(), in this order).
 
 Coding policy:
 
@@ -102,8 +110,7 @@
   can. Calls to printk/pr_debug for debugging purposes are replaced
   by calls to dev_dbg. Here is an example on how to call it (taken
   from lm75_detect):
-  dev_dbg(&adapter->dev,
-          "lm75_detect called for an ISA bus adapter?!?\n");
+  dev_dbg(&client->dev, "Starting lm75 update\n");
   Replace other printk calls with the dev_info, dev_err or dev_warn
   function, as appropriate.
 
@@ -119,3 +126,8 @@
 * [Layout] Avoid extra empty lines between comments and what they
   comment. Respect the coding style (see Documentation/CodingStyle),
   in particular when it comes to placing curly braces.
+
+* [Comments] Make sure that no comment refers to a file that isn't
+  part of the Linux source tree (typically doc/chips/<chip name>),
+  and that remaining comments still match the code. Merging comment
+  lines when possible is encouraged.
author
#9 lore raw

ChangeSet 1.1643.36.9, 2004/03/30 14:26:52-08:00, [email protected]

[PATCH] I2C: i2c documentation update (2/2)

Here is a patch to Documentation/i2c/sysfs-interface. This is mostly my intent to make the document more readable. There are also a few incorrectnesses fixed, and some comments added.

 Documentation/i2c/sysfs-interface |   78 ++++++++++++++++++--------------------
 1 files changed, 37 insertions(+), 41 deletions(-)
Documentation/i2c/sysfs-interface +37 -41
diff -Nru a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
@@ -74,18 +74,15 @@
 ************
 
 in[0-8]_min	Voltage min value.
-		Fixed point value in form XXXX.  Divide by 1000 to get
-		Volts.
+		Unit: millivolt
 		Read/Write
 		
 in[0-8]_max	Voltage max value.
-		Fixed point value in form XXXX.  Divide by 1000 to get
-		Volts.
+		Unit: millivolt
 		Read/Write
 		
 in[0-8]_input	Voltage input value.
-		Fixed point value in form XXXX.  Divide by 1000 to get
-		Volts.
+		Unit: millivolt
 		Read only
 		Actual voltage depends on the scaling resistors on the
 		motherboard, as recommended in the chip datasheet.
@@ -95,10 +92,10 @@
 		However, some drivers (notably lm87 and via686a)
 		do scale, with various degrees of success.
 		These drivers will output the actual voltage.
-		First two values are read/write and third is read only.
+
 		Typical usage:
 			in0_*	CPU #1 voltage (not scaled)
-			in1_*	CPU #1 voltage (not scaled)
+			in1_*	CPU #2 voltage (not scaled)
 			in2_*	3.3V nominal (not scaled)
 			in3_*	5.0V nominal (scaled)
 			in4_*	12.0V nominal (scaled)
@@ -108,17 +105,16 @@
 			in8_*	varies
 
 in0_ref		CPU core reference voltage.
+		Unit: millivolt
 		Read only.
-		Fixed point value in form XXXX corresponding to CPU core
-		voltage as told to the sensor chip.  Divide by 1000 to
-		get Volts.  Not always correct.
+		Not always correct.
 
 vrm		Voltage Regulator Module version number. 
 		Read only.
-		Two digit number (XX), first is major version, second is
+		Two digit number, first is major version, second is
 		minor version.
-		Affects the way the driver calculates the core voltage from
-		the vid pins. See doc/vid for details.
+		Affects the way the driver calculates the CPU core reference
+		voltage from the vid pins.
 
 
 ********
@@ -126,23 +122,23 @@
 ********
 
 fan[1-3]_min	Fan minimum value
-		Integer value indicating RPM
+		Unit: revolution/min (RPM)
 		Read/Write.
 
 fan[1-3]_input	Fan input value.
-		Integer value indicating RPM
+		Unit: revolution/min (RPM)
 		Read only.
 
 fan[1-3]_div	Fan divisor.
-		Integers in powers of two (1,2,4,8,16,32,64,128).
-		Some chips only support values 1,2,4,8.
-		See doc/fan-divisors for details.
+		Integer value in powers of two (1, 2, 4, 8, 16, 32, 64, 128).
+		Some chips only support values 1, 2, 4 and 8.
+		Note that this is actually an internal clock divisor, which
+		affects the measurable speed range, not the read value.
 
 fan[1-3]_pwm	Pulse width modulation fan control.
-		Integer 0 - 255
+		Integer value in the range 0 to 255
 		Read/Write
 		255 is max or 100%.
-		Corresponds to the fans 1-3.
 
 fan[1-3]_pwm_enable
 		Switch PWM on and off.
@@ -157,46 +153,46 @@
 ****************
 
 temp[1-3]_type	Sensor type selection.
-		Integers 1,2,3, or thermistor Beta value (3435)
+		Integers 1, 2, 3 or thermistor Beta value (3435)
 		Read/Write.
+		1: PII/Celeron Diode
+		2: 3904 transistor
+		3: thermal diode
+		Not all types are supported by all chips
 
 temp[1-4]_max	Temperature max value.
-		Fixed point value in form XXXXX and should be divided by
-		1000 to get degrees Celsius.
+		Unit: millidegree Celcius
 		Read/Write value.
 
 temp[1-3]_min	Temperature min value.
-		Fixed point value in form XXXXX and should be divided by
-		1000 to get degrees Celsius.
+		Unit: millidegree Celcius
 		Read/Write value.
 
 temp[1-3]_max_hyst
 		Temperature hysteresis value for max limit.
-		Fixed point value in form XXXXX and should be divided by
-		1000 to get degrees Celsius.  Must be reported as an
-		absolute temperature, NOT a delta from the max value.
+		Unit: millidegree Celcius
+		Must be reported as an absolute temperature, NOT a delta
+		from the max value.
 		Read/Write value.
 
 temp[1-4]_input Temperature input value.
-		Fixed point value in form XXXXX and should be divided by
-		1000 to get degrees Celsius.
+		Unit: millidegree Celcius
 		Read only value.
 
 temp[1-4]_crit	Temperature critical value, typically greater than
 		corresponding temp_max values.
-		Fixed point value in form XXXXX and should be divided by
-		1000 to get degrees Celsius.
+		Unit: millidegree Celcius
 		Read/Write value.
 
 temp[1-2]_crit_hyst
 		Temperature hysteresis value for critical limit.
-		Fixed point value in form XXXXX and should be divided by
-		1000 to get degrees Celsius.  Must be reported as an
-		absolute temperature, NOT a delta from the critical value.
+		Unit: millidegree Celcius
+		Must be reported as an absolute temperature, NOT a delta
+		from the critical value.
 		Read/Write value.
 
 		If there are multiple temperature sensors, temp1_* is
-		generally the sensor inside the chip itself, generally
+		generally the sensor inside the chip itself,
 		reported as "motherboard temperature".  temp2_* to
 		temp4_* are generally sensors external to the chip
 		itself, for example the thermal diode inside the CPU or
@@ -211,15 +207,15 @@
 so this part is theoretical, so to say.
 
 curr[1-n]_max	Current max value
-		Fixed point XXXXX, divide by 1000 to get Amps.
+		Unit: milliampere
 		Read/Write.
 
 curr[1-n]_min	Current min value.
-		Fixed point XXXXX, divide by 1000 to get Amps.
+		Unit: milliampere
 		Read/Write.
 
 curr[1-n]_input	Current input value
-		Fixed point XXXXX, divide by 1000 to get Amps.
+		Unit: milliampere
 		Read only.
 
 
@@ -246,7 +242,7 @@
 
 beep_mask	Bitmask for beep.
 		Same format as 'alarms' with the same bit locations.
-		Read only.
+		Read/Write
 
 eeprom		Raw EEPROM data in binary form.
 		Read only.
author
#10 lore raw

ChangeSet 1.1643.36.10, 2004/03/30 14:27:06-08:00, [email protected]

[PATCH] I2C: Incorrect memset in eeprom.c

Quoting Ralf Roesch:

Quoted 2 lines

currently I'm only working with Linux MIPS 2.4 kernel, so it would be nice if you could forward the patch for 2.6.

OK, so here we are. Greg, this is the port to 2.6 of Ralf patch that fixes an incorrect memset while initializing the eeprom driver. Please apply.

 drivers/i2c/chips/eeprom.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/chips/eeprom.c +1 -1
diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
@@ -197,7 +197,7 @@
 				 sizeof(struct eeprom_data));
 
 	data = (struct eeprom_data *) (new_client + 1);
-	memset(data, 0xff, EEPROM_SIZE);
+	memset(data->data, 0xff, EEPROM_SIZE);
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
author
#11 lore raw

ChangeSet 1.1643.36.11, 2004/03/30 14:27:21-08:00, [email protected]

[PATCH] I2C: Discard pointless comment in via686a

The simple patch below discards a comment in via686a referencing a file that doesn't belong to the Linux tree. Now that I tell people not to do that in my porting guide, we better follow our own advice.

 drivers/i2c/chips/via686a.c |    1 -
 1 files changed, 1 deletion(-)
drivers/i2c/chips/via686a.c +0 -1
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
@@ -27,7 +27,6 @@
 /*
     Supports the Via VT82C686A, VT82C686B south bridges.
     Reports all as a 686A.
-    See doc/chips/via686a for details.
     Warning - only supports a single device.
 */
 
author
#12 lore raw

ChangeSet 1.1643.36.12, 2004/04/02 11:02:14-08:00, [email protected]

[PATCH] I2C: Add ALi 1563 Device ID to pci_ids.h

 include/linux/pci_ids.h |    1 +
 1 files changed, 1 insertion(+)
include/linux/pci_ids.h +1 -0
diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
@@ -994,6 +994,7 @@
 #define PCI_DEVICE_ID_AL_M1531		0x1531
 #define PCI_DEVICE_ID_AL_M1533		0x1533
 #define PCI_DEVICE_ID_AL_M1541		0x1541
+#define PCI_DEVICE_ID_AL_M1563		0x1563
 #define PCI_DEVICE_ID_AL_M1621		0x1621
 #define PCI_DEVICE_ID_AL_M1631		0x1631
 #define PCI_DEVICE_ID_AL_M1632		0x1632
author
#13 lore raw

ChangeSet 1.1643.36.13, 2004/04/02 11:02:40-08:00, [email protected]

[PATCH] I2C: Add support for the ALi 1563 in the PCI IRQ routing code.

 arch/i386/pci/irq.c |    5 +++--
 1 files changed, 3 insertions(+), 2 deletions(-)
arch/i386/pci/irq.c +3 -2
diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
@@ -590,12 +590,13 @@
 {
 	switch(device)
 	{
-		case PCI_DEVICE_ID_AL_M1533:
+	case PCI_DEVICE_ID_AL_M1533:
+	case PCI_DEVICE_ID_AL_M1563:
+		printk("PCI: Using ALI IRQ Router\n");
 			r->name = "ALI";
 			r->get = pirq_ali_get;
 			r->set = pirq_ali_set;
 			return 1;
-		/* Should add 156x some day */
 	}
 	return 0;
 }
author
#14 lore raw

ChangeSet 1.1643.36.14, 2004/04/02 11:03:04-08:00, [email protected]

[PATCH] I2C: Add ALi 1563 i2c driver

The i2c interface on the 1563 is totally different than on both the 1533 and the 1535. It supports i2c 2.0, and happens to be nearly identical to the interface on the i810 chipsets.

 drivers/i2c/busses/Kconfig       |   12 +
 drivers/i2c/busses/Makefile      |    1 
 drivers/i2c/busses/i2c-ali1563.c |  421 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 434 insertions(+)
drivers/i2c/busses/Kconfig +12 -0
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
@@ -5,6 +5,18 @@
 menu "I2C Hardware Bus support"
 	depends on I2C
 
+config I2C_ALI1563
+	tristate "ALI 1563"
+	depends on I2C && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the SMB
+	  Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
+	  controller is part of the 7101 device, which is an ACPI-compliant
+	  Power Management Unit (PMU).
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called i2c-ali1563.
+
 config I2C_ALI1535
 	tristate "ALI 1535"
 	depends on I2C && PCI && EXPERIMENTAL
drivers/i2c/busses/Makefile +1 -0
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
@@ -4,6 +4,7 @@
 
 obj-$(CONFIG_I2C_ALI1535)	+= i2c-ali1535.o
 obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
+obj-$(CONFIG_I2C_ALI1563)	+= i2c-ali1563.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
drivers/i2c/busses/i2c-ali1563.c new file +421 -0

421 lines not on this page · raw message

author
#15 lore raw

ChangeSet 1.1643.36.15, 2004/04/02 11:05:14-08:00, [email protected]

[PATCH] I2C: Fix check for DEBUG in i2c-ali1563

 drivers/i2c/busses/i2c-ali1563.c |    5 -----
 1 files changed, 5 deletions(-)
drivers/i2c/busses/i2c-ali1563.c +0 -5
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
@@ -15,11 +15,6 @@
  *	This file is released under the GPLv2
  */
 
-#include <linux/config.h>
-#ifdef CONFIG_I2C_DEBUG_BUS
-#define DEBUG 0
-#endif
-
 #include <linux/module.h>
 #include <linux/i2c.h>
 #include <linux/pci.h>
author
#16 lore raw

ChangeSet 1.1643.36.16, 2004/04/08 10:23:27-07:00, [email protected]

[PATCH] I2C: Refactor swap_bytes in i2c chip drivers

Quoted 3 lines

Ick, no, we should be using the proper kernel call for this, swab16(), right? Care to redo this patch to just fix the drivers and get rid of our duplicating of this function.

Oh, I didn't know such a function existed, sorry.

Here's a new patch, hope you like it. Tested to work on my as99127f, btw (w83781d driver).

Documentation update follows (well, tomorrow it does).

 drivers/i2c/chips/asb100.c  |   15 +++++----------
 drivers/i2c/chips/ds1621.c  |   10 ++--------
 drivers/i2c/chips/gl518sm.c |   10 ++--------
 drivers/i2c/chips/lm75.c    |   10 ++--------
 drivers/i2c/chips/w83781d.c |   20 +++++---------------
 5 files changed, 16 insertions(+), 49 deletions(-)
drivers/i2c/chips/asb100.c +5 -10
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
@@ -862,11 +862,6 @@
 	return 0;
 }
 
-static u16 swap_bytes(u16 val)
-{
-	return (val >> 8) | (val << 8);
-}
-
 /* The SMBus locks itself, usually, but nothing may access the chip between
    bank switches. */
 static int asb100_read_value(struct i2c_client *client, u16 reg)
@@ -891,17 +886,17 @@
 		/* convert from ISA to LM75 I2C addresses */
 		switch (reg & 0xff) {
 		case 0x50: /* TEMP */
-			res = swap_bytes(i2c_smbus_read_word_data (cl, 0));
+			res = swab16(i2c_smbus_read_word_data (cl, 0));
 			break;
 		case 0x52: /* CONFIG */
 			res = i2c_smbus_read_byte_data(cl, 1);
 			break;
 		case 0x53: /* HYST */
-			res = swap_bytes(i2c_smbus_read_word_data (cl, 2));
+			res = swab16(i2c_smbus_read_word_data (cl, 2));
 			break;
 		case 0x55: /* MAX */
 		default:
-			res = swap_bytes(i2c_smbus_read_word_data (cl, 3));
+			res = swab16(i2c_smbus_read_word_data (cl, 3));
 			break;
 		}
 	}
@@ -939,10 +934,10 @@
 			i2c_smbus_write_byte_data(cl, 1, value & 0xff);
 			break;
 		case 0x53: /* HYST */
-			i2c_smbus_write_word_data(cl, 2, swap_bytes(value));
+			i2c_smbus_write_word_data(cl, 2, swab16(value));
 			break;
 		case 0x55: /* MAX */
-			i2c_smbus_write_word_data(cl, 3, swap_bytes(value));
+			i2c_smbus_write_word_data(cl, 3, swab16(value));
 			break;
 		}
 	}
drivers/i2c/chips/ds1621.c +2 -8
diff -Nru a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
@@ -97,11 +97,6 @@
 
 static int ds1621_id = 0;
 
-static u16 swap_bytes(u16 val)
-{
-	return (val >> 8) | (val << 8);
-}
-
 /* All registers are word-sized, except for the configuration register.
    DS1621 uses a high-byte first convention, which is exactly opposite to
    the usual practice. */
@@ -110,7 +105,7 @@
 	if (reg == DS1621_REG_CONF)
 		return i2c_smbus_read_byte_data(client, reg);
 	else
-		return swap_bytes(i2c_smbus_read_word_data(client, reg));
+		return swab16(i2c_smbus_read_word_data(client, reg));
 }
 
 /* All registers are word-sized, except for the configuration register.
@@ -121,8 +116,7 @@
 	if (reg == DS1621_REG_CONF)
 		return i2c_smbus_write_byte_data(client, reg, value);
 	else
-		return i2c_smbus_write_word_data(client, reg,
-						 swap_bytes(value));
+		return i2c_smbus_write_word_data(client, reg, swab16(value));
 }
 
 static void ds1621_init_client(struct i2c_client *client)
drivers/i2c/chips/gl518sm.c +2 -8
diff -Nru a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
@@ -484,18 +484,13 @@
 	return 0;
 }
 
-static inline u16 swap_bytes(u16 val)
-{
-	return (val >> 8) | (val << 8);
-}
-
 /* Registers 0x07 to 0x0c are word-sized, others are byte-sized 
    GL518 uses a high-byte first convention, which is exactly opposite to
    the usual practice. */
 static int gl518_read_value(struct i2c_client *client, u8 reg)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return swap_bytes(i2c_smbus_read_word_data(client, reg));
+		return swab16(i2c_smbus_read_word_data(client, reg));
 	else
 		return i2c_smbus_read_byte_data(client, reg);
 }
@@ -506,8 +501,7 @@
 static int gl518_write_value(struct i2c_client *client, u8 reg, u16 value)
 {
 	if ((reg >= 0x07) && (reg <= 0x0c))
-		return i2c_smbus_write_word_data(client, reg,
-						 swap_bytes(value));
+		return i2c_smbus_write_word_data(client, reg, swab16(value));
 	else
 		return i2c_smbus_write_byte_data(client, reg, value);
 }
drivers/i2c/chips/lm75.c +2 -8
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
@@ -206,11 +206,6 @@
 	return 0;
 }
 
-static u16 swap_bytes(u16 val)
-{
-	return (val >> 8) | (val << 8);
-}
-
 /* All registers are word-sized, except for the configuration register.
    LM75 uses a high-byte first convention, which is exactly opposite to
    the usual practice. */
@@ -219,7 +214,7 @@
 	if (reg == LM75_REG_CONF)
 		return i2c_smbus_read_byte_data(client, reg);
 	else
-		return swap_bytes(i2c_smbus_read_word_data(client, reg));
+		return swab16(i2c_smbus_read_word_data(client, reg));
 }
 
 /* All registers are word-sized, except for the configuration register.
@@ -230,8 +225,7 @@
 	if (reg == LM75_REG_CONF)
 		return i2c_smbus_write_byte_data(client, reg, value);
 	else
-		return i2c_smbus_write_word_data(client, reg,
-						 swap_bytes(value));
+		return i2c_smbus_write_word_data(client, reg, swab16(value));
 }
 
 static void lm75_init_client(struct i2c_client *client)
drivers/i2c/chips/w83781d.c +5 -15
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
@@ -275,11 +275,6 @@
 static struct w83781d_data *w83781d_update_device(struct device *dev);
 static void w83781d_init_client(struct i2c_client *client);
 
-static inline u16 swap_bytes(u16 val)
-{
-	return (val >> 8) | (val << 8);
-}
-
 static struct i2c_driver w83781d_driver = {
 	.owner = THIS_MODULE,
 	.name = "w83781d",
@@ -1407,20 +1402,17 @@
 			/* convert from ISA to LM75 I2C addresses */
 			switch (reg & 0xff) {
 			case 0x50:	/* TEMP */
-				res =
-				    swap_bytes(i2c_smbus_read_word_data(cl, 0));
+				res = swab16(i2c_smbus_read_word_data(cl, 0));
 				break;
 			case 0x52:	/* CONFIG */
 				res = i2c_smbus_read_byte_data(cl, 1);
 				break;
 			case 0x53:	/* HYST */
-				res =
-				    swap_bytes(i2c_smbus_read_word_data(cl, 2));
+				res = swab16(i2c_smbus_read_word_data(cl, 2));
 				break;
 			case 0x55:	/* OVER */
 			default:
-				res =
-				    swap_bytes(i2c_smbus_read_word_data(cl, 3));
+				res = swab16(i2c_smbus_read_word_data(cl, 3));
 				break;
 			}
 		}
@@ -1481,12 +1473,10 @@
 				i2c_smbus_write_byte_data(cl, 1, value & 0xff);
 				break;
 			case 0x53:	/* HYST */
-				i2c_smbus_write_word_data(cl, 2,
-							  swap_bytes(value));
+				i2c_smbus_write_word_data(cl, 2, swab16(value));
 				break;
 			case 0x55:	/* OVER */
-				i2c_smbus_write_word_data(cl, 3,
-							  swap_bytes(value));
+				i2c_smbus_write_word_data(cl, 3, swab16(value));
 				break;
 			}
 		}
author
#17 lore raw

ChangeSet 1.1643.36.17, 2004/04/08 14:12:22-07:00, [email protected]

[PATCH] I2C: class fixup for the ali1563 driver

 drivers/i2c/busses/i2c-ali1563.c |    1 +
 1 files changed, 1 insertion(+)
drivers/i2c/busses/i2c-ali1563.c +1 -0
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
@@ -357,6 +357,7 @@
 
 static struct i2c_adapter ali1563_adapter = {
 	.owner	= THIS_MODULE,
+	.class	= I2C_ADAP_CLASS_SMBUS,
 	.algo	= &ali1563_algorithm,
 };
 
author
#18 lore raw

ChangeSet 1.1643.36.18, 2004/04/08 14:12:39-07:00, [email protected]

[PATCH] I2C: i2c-ali1563.c section fix

ali1563_shutdown() is called from __init ali1563_probe() and hence cannot be marked __init.

 drivers/i2c/busses/i2c-ali1563.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/busses/i2c-ali1563.c +1 -1
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
@@ -343,7 +343,7 @@
 	return -ENODEV;
 }
 
-static void __exit ali1563_shutdown(struct pci_dev * dev)
+static void ali1563_shutdown(struct pci_dev *dev)
 {
 	release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
 }
author
#19 lore raw

ChangeSet 1.1643.36.19, 2004/04/09 11:58:21-07:00, [email protected]

[PATCH] I2C: Enable changing fan_divs in lm80 driver

For some reason the original lm80 driver in 2.6 cannot set fan_divs (while the 2.4 driver could). This patch brings support back. It was lightly tested by one user.

This patch also suggests some code cleanups (fan code refactoring). I'll send a different patch later for these.

 drivers/i2c/chips/lm80.c |   57 ++++++++++++++++++++++++++++++++++++++++-------
 1 files changed, 49 insertions(+), 8 deletions(-)
drivers/i2c/chips/lm80.c +49 -8
diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
@@ -44,10 +44,9 @@
 #define LM80_REG_IN_MIN(nr)		(0x2b + (nr) * 2)
 #define LM80_REG_IN(nr)			(0x20 + (nr))
 
-#define LM80_REG_FAN1_MIN		0x3c
-#define LM80_REG_FAN2_MIN		0x3d
 #define LM80_REG_FAN1			0x28
 #define LM80_REG_FAN2			0x29
+#define LM80_REG_FAN_MIN(nr)		(0x3b + (nr))
 
 #define LM80_REG_TEMP			0x27
 #define LM80_REG_TEMP_HOT_MAX		0x38
@@ -250,8 +249,46 @@
 	lm80_write_value(client, reg, data->value); \
 	return count; \
 }
-set_fan(min1, fan_min[0], LM80_REG_FAN1_MIN, fan_div[0]);
-set_fan(min2, fan_min[1], LM80_REG_FAN2_MIN, fan_div[1]);
+set_fan(min1, fan_min[0], LM80_REG_FAN_MIN(1), fan_div[0]);
+set_fan(min2, fan_min[1], LM80_REG_FAN_MIN(2), fan_div[1]);
+
+/* Note: we save and restore the fan minimum here, because its value is
+   determined in part by the fan divisor.  This follows the principle of
+   least suprise; the user doesn't expect the fan minimum to change just
+   because the divisor changed. */
+static ssize_t set_fan_div(struct device *dev, const char *buf,
+	size_t count, int nr)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct lm80_data *data = i2c_get_clientdata(client);
+	unsigned long min;
+	u8 reg;
+
+	/* Save fan_min */
+	min = FAN_FROM_REG(data->fan_min[nr],
+			   DIV_FROM_REG(data->fan_div[nr]));
+
+	data->fan_div[nr] = DIV_TO_REG(simple_strtoul(buf, NULL, 10));
+
+	reg = (lm80_read_value(client, LM80_REG_FANDIV) & ~(3 << (2 * (nr + 1))))
+	    | (data->fan_div[nr] << (2 * (nr + 1)));
+	lm80_write_value(client, LM80_REG_FANDIV, reg);
+
+	/* Restore fan_min */
+	data->fan_min[nr] = FAN_TO_REG(min, DIV_FROM_REG(data->fan_div[nr]));
+	lm80_write_value(client, LM80_REG_FAN_MIN(nr + 1), data->fan_min[nr]);
+
+	return count;
+}
+
+#define set_fan_div(number) \
+static ssize_t set_fan_div##number(struct device *dev, const char *buf, \
+	size_t count) \
+{ \
+	return set_fan_div(dev, buf, count, number - 1); \
+}
+set_fan_div(1);
+set_fan_div(2);
 
 static ssize_t show_temp_input1(struct device *dev, char *buf)
 {
@@ -319,8 +356,8 @@
     set_fan_min2);
 static DEVICE_ATTR(fan1_input, S_IRUGO, show_fan_input1, NULL);
 static DEVICE_ATTR(fan2_input, S_IRUGO, show_fan_input2, NULL);
-static DEVICE_ATTR(fan1_div, S_IRUGO, show_fan_div1, NULL);
-static DEVICE_ATTR(fan2_div, S_IRUGO, show_fan_div2, NULL);
+static DEVICE_ATTR(fan1_div, S_IWUSR | S_IRUGO, show_fan_div1, set_fan_div1);
+static DEVICE_ATTR(fan2_div, S_IWUSR | S_IRUGO, show_fan_div2, set_fan_div2);
 static DEVICE_ATTR(temp1_input, S_IRUGO, show_temp_input1, NULL);
 static DEVICE_ATTR(temp1_max, S_IWUSR | S_IRUGO, show_temp_hot_max,
     set_temp_hot_max);
@@ -401,6 +438,10 @@
 	/* Initialize the LM80 chip */
 	lm80_init_client(new_client);
 
+	/* A few vars need to be filled upon startup */
+	data->fan_min[0] = lm80_read_value(new_client, LM80_REG_FAN_MIN(1));
+	data->fan_min[1] = lm80_read_value(new_client, LM80_REG_FAN_MIN(2));
+
 	/* Register sysfs hooks */
 	device_create_file(&new_client->dev, &dev_attr_in0_min);
 	device_create_file(&new_client->dev, &dev_attr_in1_min);
@@ -504,10 +545,10 @@
 		}
 		data->fan[0] = lm80_read_value(client, LM80_REG_FAN1);
 		data->fan_min[0] =
-		    lm80_read_value(client, LM80_REG_FAN1_MIN);
+		    lm80_read_value(client, LM80_REG_FAN_MIN(1));
 		data->fan[1] = lm80_read_value(client, LM80_REG_FAN2);
 		data->fan_min[1] =
-		    lm80_read_value(client, LM80_REG_FAN2_MIN);
+		    lm80_read_value(client, LM80_REG_FAN_MIN(2));
 
 		data->temp =
 		    (lm80_read_value(client, LM80_REG_TEMP) << 8) |
author
#20 lore raw

ChangeSet 1.1643.36.20, 2004/04/09 12:05:44-07:00, [email protected]

[PATCH] I2C: New chip driver: pcf8591

Please find below a patch against kernel 2.6.5-rc2-mm4 to add the pcf8591 driver (a 8-bit A/D and D/A converter). I have ported it from the 2.4 version, and it includes some fixes, improvements and simplifications.

It has been reviewed by Jean Delvare on IRC.

Please also note that the patch also fixes a missing space in drivers/i2c/chips/Kconfig, introduced by the previous patch I sent you concerning the pcf8574.

 drivers/i2c/chips/Kconfig   |   12 +
 drivers/i2c/chips/Makefile  |    1 
 drivers/i2c/chips/pcf8591.c |  321 ++++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 333 insertions(+), 1 deletion(-)
drivers/i2c/chips/Kconfig +11 -1
diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
@@ -217,7 +217,17 @@
 	  If you say yes here you get support for Philips PCF8574 and 
 	  PCF8574A chips.
 
-	  This driver can also be built as a module. If so, the module
+	  This driver can also be built as a module.  If so, the module
 	  will be called pcf8574.
+
+config SENSORS_PCF8591
+	tristate "Philips PCF8591"
+	depends on I2C && EXPERIMENTAL
+	select I2C_SENSOR
+	help
+	  If you say yes here you get support for Philips PCF8591 chips.
+
+	  This driver can also be built as a module.  If so, the module
+	  will be called pcf8591.
 
 endmenu
drivers/i2c/chips/Makefile +1 -0
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
@@ -20,6 +20,7 @@
 obj-$(CONFIG_SENSORS_LM85)	+= lm85.o
 obj-$(CONFIG_SENSORS_LM90)	+= lm90.o
 obj-$(CONFIG_SENSORS_PCF8574)	+= pcf8574.o
+obj-$(CONFIG_SENSORS_PCF8591)	+= pcf8591.o
 obj-$(CONFIG_SENSORS_VIA686A)	+= via686a.o
 obj-$(CONFIG_SENSORS_W83L785TS)	+= w83l785ts.o
 
drivers/i2c/chips/pcf8591.c new file +321 -0

321 lines not on this page · raw message

author
#21 lore raw

ChangeSet 1.1643.36.21, 2004/04/09 12:06:02-07:00, [email protected]

[PATCH] I2C: minor bugfixes for the pcf8591.c driver and formatting cleanups.

 drivers/i2c/chips/pcf8591.c |   10 ++++------
 1 files changed, 4 insertions(+), 6 deletions(-)
drivers/i2c/chips/pcf8591.c +4 -6
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
@@ -125,8 +125,7 @@
 	unsigned int value;
 	struct i2c_client *client = to_i2c_client(dev);
 	struct pcf8591_data *data = i2c_get_clientdata(client);
-	if ((value = (simple_strtoul(buf, NULL, 10) + 5) / 10) <= 255);
-	{
+	if ((value = (simple_strtoul(buf, NULL, 10) + 5) / 10) <= 255) {
 		data->aout = value;
 		i2c_smbus_write_byte_data(client, data->control, data->aout);
 	}
@@ -235,9 +234,9 @@
 	/* OK, this is not exactly good programming practice, usually. But it is
 	   very code-efficient in this case. */
 
-      exit_kfree:
+exit_kfree:
 	kfree(new_client);
-      exit:
+exit:
 	return err;
 }
 
@@ -277,8 +276,7 @@
 
 	down(&data->update_lock);
 
-	if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel)
-	{
+	if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel) {
 		data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK)
 			      | channel;
 		i2c_smbus_write_byte(client, data->control);
author
#22 lore raw

ChangeSet 1.1643.36.22, 2004/04/09 12:06:16-07:00, [email protected]

[PATCH] I2C: clean up out of order bus Makefile and Kconfig entries.

 drivers/i2c/busses/Kconfig  |   16 ++++++++--------
 drivers/i2c/busses/Makefile |    2 +-
 2 files changed, 9 insertions(+), 9 deletions(-)
drivers/i2c/busses/Kconfig +8 -8
diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
@@ -5,29 +5,29 @@
 menu "I2C Hardware Bus support"
 	depends on I2C
 
-config I2C_ALI1563
-	tristate "ALI 1563"
+config I2C_ALI1535
+	tristate "ALI 1535"
 	depends on I2C && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the SMB
-	  Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
+	  Host controller on Acer Labs Inc. (ALI) M1535 South Bridges.  The SMB
 	  controller is part of the 7101 device, which is an ACPI-compliant
 	  Power Management Unit (PMU).
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called i2c-ali1563.
+	  will be called i2c-ali1535.
 
-config I2C_ALI1535
-	tristate "ALI 1535"
+config I2C_ALI1563
+	tristate "ALI 1563"
 	depends on I2C && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the SMB
-	  Host controller on Acer Labs Inc. (ALI) M1535 South Bridges.  The SMB
+	  Host controller on Acer Labs Inc. (ALI) M1563 South Bridges.  The SMB
 	  controller is part of the 7101 device, which is an ACPI-compliant
 	  Power Management Unit (PMU).
 
 	  This driver can also be built as a module.  If so, the module
-	  will be called i2c-ali1535.
+	  will be called i2c-ali1563.
 
 config I2C_ALI15X3
 	tristate "ALI 15x3"
drivers/i2c/busses/Makefile +1 -1
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
@@ -3,8 +3,8 @@
 #
 
 obj-$(CONFIG_I2C_ALI1535)	+= i2c-ali1535.o
-obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_ALI1563)	+= i2c-ali1563.o
+obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_ELEKTOR)	+= i2c-elektor.o
author
#23 lore raw

ChangeSet 1.1643.36.23, 2004/04/12 15:15:13-07:00, [email protected]

[PATCH] I2C: Rework memory allocation in i2c chip drivers

Additional remarks:

1* This patch also removes an unused struct member in via686a and fixes an error message in ds1621.

2* I discovered error path problems in it87 and via686a detection functions. For the it87, I think that this patch makes it even more broken. I will fix both drivers in a later patch (really soon).

 drivers/i2c/chips/adm1021.c   |   14 ++++++--------
 drivers/i2c/chips/asb100.c    |   14 ++++++--------
 drivers/i2c/chips/ds1621.c    |   18 ++++++++----------
 drivers/i2c/chips/eeprom.c    |   14 ++++++--------
 drivers/i2c/chips/fscher.c    |   17 ++++++++---------
 drivers/i2c/chips/gl518sm.c   |   14 ++++++--------
 drivers/i2c/chips/it87.c      |   16 +++++++---------
 drivers/i2c/chips/lm75.c      |   14 ++++++--------
 drivers/i2c/chips/lm78.c      |   14 ++++++--------
 drivers/i2c/chips/lm80.c      |   13 ++++++-------
 drivers/i2c/chips/lm83.c      |   17 ++++++++---------
 drivers/i2c/chips/lm85.c      |   14 ++++++--------
 drivers/i2c/chips/lm90.c      |   17 ++++++++---------
 drivers/i2c/chips/pcf8574.c   |   15 ++++++---------
 drivers/i2c/chips/pcf8591.c   |   15 ++++++---------
 drivers/i2c/chips/via686a.c   |   16 ++++++----------
 drivers/i2c/chips/w83627hf.c  |   15 ++++++---------
 drivers/i2c/chips/w83781d.c   |   14 ++++++--------
 drivers/i2c/chips/w83l785ts.c |   18 ++++++++----------
 19 files changed, 125 insertions(+), 164 deletions(-)
drivers/i2c/chips/adm1021.c +6 -8
diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
@@ -101,6 +101,7 @@
 
 /* Each client has this additional data */
 struct adm1021_data {
+	struct i2c_client client;
 	enum chips type;
 
 	struct semaphore update_lock;
@@ -228,16 +229,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access adm1021_{read,write}_value. */
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct adm1021_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct adm1021_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto error0;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-				 sizeof(struct adm1021_data));
+	memset(data, 0, sizeof(struct adm1021_data));
 
-	data = (struct adm1021_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -329,7 +327,7 @@
 	return 0;
 
 error1:
-	kfree(new_client);
+	kfree(data);
 error0:
 	return err;
 }
@@ -352,7 +350,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/asb100.c +6 -8
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
@@ -193,6 +193,7 @@
    data is pointed to by client->data. The structure itself is
    dynamically allocated, at the same time the client itself is allocated. */
 struct asb100_data {
+	struct i2c_client client;
 	struct semaphore lock;
 	enum chips type;
 
@@ -722,17 +723,14 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access asb100_{read,write}_value. */
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-			sizeof(struct asb100_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct asb100_data), GFP_KERNEL))) {
 		pr_debug("asb100.o: detect failed, kmalloc failed!\n");
 		err = -ENOMEM;
 		goto ERROR0;
 	}
+	memset(data, 0, sizeof(struct asb100_data));
 
-	memset(new_client, 0,
-		sizeof(struct i2c_client) + sizeof(struct asb100_data));
-
-	data = (struct asb100_data *) (new_client + 1);
+	new_client = &data->client;
 	init_MUTEX(&data->lock);
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
@@ -842,7 +840,7 @@
 ERROR2:
 	i2c_detach_client(new_client);
 ERROR1:
-	kfree(new_client);
+	kfree(data);
 ERROR0:
 	return err;
 }
@@ -857,7 +855,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/ds1621.c +8 -10
diff -Nru a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
@@ -70,6 +70,7 @@
 
 /* Each client has this additional data */
 struct ds1621_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid;			/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -196,16 +197,13 @@
 	/* 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 ds1621_{read,write}_value. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct ds1621_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct ds1621_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0, sizeof(struct i2c_client) +
-	       sizeof(struct ds1621_data));
+	memset(data, 0, sizeof(struct ds1621_data));
 	
-	data = (struct ds1621_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -258,7 +256,7 @@
 /* OK, this is not exactly good programming practice, usually. But it is
    very code-efficient in this case. */
       exit_free:
-	kfree(new_client);
+	kfree(data);
       exit:
 	return err;
 }
@@ -268,12 +266,12 @@
 	int err;
 
 	if ((err = i2c_detach_client(client))) {
-		dev_err(&client->dev,
-		        "ds1621.o: Client deregistration failed, client not detached.\n");
+		dev_err(&client->dev, "Client deregistration failed, "
+			"client not detached.\n");
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/eeprom.c +6 -8
diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
@@ -63,6 +63,7 @@
 
 /* Each client has this additional data */
 struct eeprom_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 	u8 valid;			/* bitfield, bit!=0 if slice is valid */
 	unsigned long last_updated[8];	/* In jiffies, 8 slices */
@@ -187,16 +188,13 @@
 	/* 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 eeprom_{read,write}_value. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct eeprom_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-				 sizeof(struct eeprom_data));
+	memset(data, 0, sizeof(struct eeprom_data));
 
-	data = (struct eeprom_data *) (new_client + 1);
+	new_client = &data->client;
 	memset(data->data, 0xff, EEPROM_SIZE);
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
@@ -244,7 +242,7 @@
 	return 0;
 
 exit_kfree:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -259,7 +257,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/fscher.c +8 -9
diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
@@ -133,6 +133,7 @@
  */
 
 struct fscher_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -309,17 +310,15 @@
 	/* 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 i2c_smbus_read_byte_data. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-	    sizeof(struct fscher_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct fscher_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
   	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-	       sizeof(struct fscher_data));
+	memset(data, 0, sizeof(struct fscher_data));
 
-	/* The Hermes-specific data is placed right after the common I2C
-	 * client data. */
-	data = (struct fscher_data *) (new_client + 1);
+	/* The common I2C client data is placed right before the
+	 * Hermes-specific data. */
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -371,7 +370,7 @@
 	return 0;
 
 exit_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -386,7 +385,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/gl518sm.c +6 -8
diff -Nru a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
@@ -118,6 +118,7 @@
 
 /* Each client has this additional data */
 struct gl518_data {
+	struct i2c_client client;
 	enum chips type;
 
 	struct semaphore update_lock;
@@ -354,16 +355,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access gl518_{read,write}_value. */
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct gl518_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct gl518_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-		sizeof(struct gl518_data));
+	memset(data, 0, sizeof(struct gl518_data));
 
-	data = (struct gl518_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 
 	new_client->addr = address;
@@ -445,7 +443,7 @@
    very code-efficient in this case. */
 
 exit_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -479,7 +477,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/it87.c +7 -9
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
@@ -134,6 +134,7 @@
    dynamically allocated, at the same time when a new it87 client is
    allocated. */
 struct it87_data {
+	struct i2c_client client;
 	struct semaphore lock;
 	enum chips type;
 
@@ -508,7 +509,7 @@
 int it87_detect(struct i2c_adapter *adapter, int address, int kind)
 {
 	int i;
-	struct i2c_client *new_client = NULL;
+	struct i2c_client *new_client;
 	struct it87_data *data;
 	int err = 0;
 	const char *name = "";
@@ -554,16 +555,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access it87_{read,write}_value. */
 
-	if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
-					sizeof(struct it87_data),
-					GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct it87_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-				 sizeof(struct it87_data));
+	memset(data, 0, sizeof(struct it87_data));
 
-	data = (struct it87_data *) (new_client + 1);
+	new_client = &data->client;
 	if (is_isa)
 		init_MUTEX(&data->lock);
 	i2c_set_clientdata(new_client, data);
@@ -670,7 +668,7 @@
 	return 0;
 
 ERROR1:
-	kfree(new_client);
+	kfree(data);
 
 	if (is_isa)
 		release_region(address, IT87_EXTENT);
@@ -690,7 +688,7 @@
 
 	if(i2c_is_isa_client(client))
 		release_region(client->addr, IT87_EXTENT);
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/lm75.c +6 -8
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
@@ -46,6 +46,7 @@
 
 /* Each client has this additional data */
 struct lm75_data {
+	struct i2c_client	client;
 	struct semaphore	update_lock;
 	char			valid;		/* !=0 if following fields are valid */
 	unsigned long		last_updated;	/* In jiffies */
@@ -135,16 +136,13 @@
 	/* 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 lm75_{read,write}_value. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct lm75_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct lm75_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-				 sizeof(struct lm75_data));
+	memset(data, 0, sizeof(struct lm75_data));
 
-	data = (struct lm75_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -194,7 +192,7 @@
 	return 0;
 
 exit_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -202,7 +200,7 @@
 static int lm75_detach_client(struct i2c_client *client)
 {
 	i2c_detach_client(client);
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/lm78.c +6 -8
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
@@ -192,6 +192,7 @@
    dynamically allocated, at the same time when a new lm78 client is
    allocated. */
 struct lm78_data {
+	struct i2c_client client;
 	struct semaphore lock;
 	enum chips type;
 
@@ -552,16 +553,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm78_{read,write}_value. */
 
-	if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
-				   sizeof(struct lm78_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct lm78_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
-	memset(new_client, 0, sizeof(struct i2c_client) + 
-			      sizeof(struct lm78_data));
+	memset(data, 0, sizeof(struct lm78_data));
 
-	data = (struct lm78_data *) (new_client + 1);
+	new_client = &data->client;
 	if (is_isa)
 		init_MUTEX(&data->lock);
 	i2c_set_clientdata(new_client, data);
@@ -671,7 +669,7 @@
 	return 0;
 
 ERROR2:
-	kfree(new_client);
+	kfree(data);
 ERROR1:
 	if (is_isa)
 		release_region(address, LM78_EXTENT);
@@ -694,7 +692,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/lm80.c +6 -7
diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
@@ -110,6 +110,7 @@
  */
 
 struct lm80_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -394,15 +395,13 @@
 	/* 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 lm80_{read,write}_value. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-	    sizeof(struct lm80_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct lm80_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-	       sizeof(struct lm80_data));
+	memset(data, 0, sizeof(struct lm80_data));
 
-	data = (struct lm80_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -480,7 +479,7 @@
 	return 0;
 
 error_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -495,7 +494,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/lm83.c +8 -9
diff -Nru a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
@@ -134,6 +134,7 @@
  */
 
 struct lm83_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -234,17 +235,15 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-	    sizeof(struct lm83_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct lm83_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-	    sizeof(struct lm83_data));
+	memset(data, 0, sizeof(struct lm83_data));
 
-	/* The LM83-specific data is placed right after the common I2C
-	 * client data. */
-	data = (struct lm83_data *) (new_client + 1);
+	/* The common I2C client data is placed right after the
+	 * LM83-specific data. */
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -329,7 +328,7 @@
 	return 0;
 
 exit_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -344,7 +343,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/lm85.c +6 -8
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
@@ -351,6 +351,7 @@
 };
 
 struct lm85_data {
+	struct i2c_client client;
 	struct semaphore lock;
 	enum chips type;
 
@@ -736,16 +737,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access lm85_{read,write}_value. */
 
-	if (!(new_client = kmalloc((sizeof(struct i2c_client)) +
-				    sizeof(struct lm85_data),
-				    GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct lm85_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR0;
 	}
+	memset(data, 0, sizeof(struct lm85_data));
 
-	memset(new_client, 0, sizeof(struct i2c_client) +
-			      sizeof(struct lm85_data));
-	data = (struct lm85_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -886,7 +884,7 @@
 
 	/* Error out and cleanup code */
     ERROR1:
-	kfree(new_client);
+	kfree(data);
     ERROR0:
 	return err;
 }
@@ -894,7 +892,7 @@
 int lm85_detach_client(struct i2c_client *client)
 {
 	i2c_detach_client(client);
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/lm90.c +8 -9
diff -Nru a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
@@ -142,6 +142,7 @@
  */
 
 struct lm90_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -280,17 +281,15 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-	    sizeof(struct lm90_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct lm90_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-	       sizeof(struct lm90_data));
+	memset(data, 0, sizeof(struct lm90_data));
 
-	/* The LM90-specific data is placed right after the common I2C
-	 * client data. */
-	data = (struct lm90_data *) (new_client + 1);
+	/* The common I2C client data is placed right before the
+	   LM90-specific data. */
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -390,7 +389,7 @@
 	return 0;
 
 exit_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -420,7 +419,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/pcf8574.c +6 -9
diff -Nru a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
@@ -55,6 +55,7 @@
 
 /* Each client has this additional data */
 struct pcf8574_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 
 	u8 read, write;			/* Register values */
@@ -127,17 +128,13 @@
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct pcf8574_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct pcf8574_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
+	memset(data, 0, sizeof(struct pcf8574_data));
 
-	memset(new_client, 0, sizeof(struct i2c_client) +
-	       sizeof(struct pcf8574_data));
-
-	data = (struct pcf8574_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -182,7 +179,7 @@
    very code-efficient in this case. */
 
       exit_free:
-	kfree(new_client);
+	kfree(data);
       exit:
 	return err;
 }
@@ -197,7 +194,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/pcf8591.c +6 -9
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
@@ -76,6 +76,7 @@
 #define REG_TO_SIGNED(reg)	(((reg) & 0x80)?((reg) - 256):(reg))
 
 struct pcf8591_data {
+	struct i2c_client client;
 	struct semaphore update_lock;
 
 	u8 control;
@@ -177,17 +178,13 @@
 
 	/* OK. For now, we presume we have a valid client. We now create the
 	   client structure, even though we cannot fill it completely yet. */
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct pcf8591_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct pcf8591_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-
-	memset(new_client, 0, sizeof(struct i2c_client) +
-			      sizeof(struct pcf8591_data));
+	memset(data, 0, sizeof(struct pcf8591_data));
 	
-	data = (struct pcf8591_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -235,7 +232,7 @@
 	   very code-efficient in this case. */
 
 exit_kfree:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -250,7 +247,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
drivers/i2c/chips/via686a.c +6 -10
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
@@ -369,8 +369,7 @@
    dynamically allocated, at the same time when a new via686a client is
    allocated. */
 struct via686a_data {
-	int sysctl_id;
-
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid;		/* !=0 if following fields are valid */
 	unsigned long last_updated;	/* In jiffies */
@@ -687,16 +686,13 @@
 		return -ENODEV;
 	}
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct via686a_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct via686a_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR0;
 	}
+	memset(data, 0, sizeof(struct via686a_data));
 
-	memset(new_client,0x00, sizeof(struct i2c_client) +
-				sizeof(struct via686a_data));
-	data = (struct via686a_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -753,7 +749,7 @@
 
       ERROR3:
 	release_region(address, VIA686A_EXTENT);
-	kfree(new_client);
+	kfree(data);
       ERROR0:
 	return err;
 }
@@ -769,7 +765,7 @@
 	}
 
 	release_region(client->addr, VIA686A_EXTENT);
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/w83627hf.c +6 -9
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
@@ -277,6 +277,7 @@
    data is pointed to by w83627hf_list[NR]->data. The structure itself is
    dynamically allocated, at the same time when a new client is allocated. */
 struct w83627hf_data {
+	struct i2c_client client;
 	struct semaphore lock;
 	enum chips type;
 
@@ -941,17 +942,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access w83627hf_{read,write}_value. */
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
-				   sizeof(struct w83627hf_data),
-				   GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct w83627hf_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
+	memset(data, 0, sizeof(struct w83627hf_data));
 
-	memset(new_client, 0x00, sizeof (struct i2c_client) +
-	       sizeof (struct w83627hf_data));
-
-	data = (struct w83627hf_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	init_MUTEX(&data->lock);
@@ -1042,7 +1039,7 @@
 	return 0;
 
       ERROR2:
-	kfree(new_client);
+	kfree(data);
       ERROR1:
 	release_region(address, WINB_EXTENT);
       ERROR0:
@@ -1060,7 +1057,7 @@
 	}
 
 	release_region(client->addr, WINB_EXTENT);
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/w83781d.c +6 -8
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
@@ -226,6 +226,7 @@
    dynamically allocated, at the same time when a new w83781d client is
    allocated. */
 struct w83781d_data {
+	struct i2c_client client;
 	struct semaphore lock;
 	enum chips type;
 
@@ -1112,16 +1113,13 @@
 	   client structure, even though we cannot fill it completely yet.
 	   But it allows us to access w83781d_{read,write}_value. */
 
-	if (!(new_client = kmalloc(sizeof (struct i2c_client) +
-				   sizeof (struct w83781d_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct w83781d_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto ERROR1;
 	}
+	memset(data, 0, sizeof(struct w83781d_data));
 
-	memset(new_client, 0x00, sizeof (struct i2c_client) +
-	       sizeof (struct w83781d_data));
-
-	data = (struct w83781d_data *) (new_client + 1);
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	init_MUTEX(&data->lock);
@@ -1321,7 +1319,7 @@
 ERROR3:
 	i2c_detach_client(new_client);
 ERROR2:
-	kfree(new_client);
+	kfree(data);
 ERROR1:
 	if (is_isa)
 		release_region(address, W83781D_EXTENT);
@@ -1343,7 +1341,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 
 	return 0;
 }
drivers/i2c/chips/w83l785ts.c +8 -10
diff -Nru a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
@@ -105,7 +105,7 @@
  */
 
 struct w83l785ts_data {
-	
+	struct i2c_client client;
 	struct semaphore update_lock;
 	char valid; /* zero until following fields are valid */
 	unsigned long last_updated; /* in jiffies */
@@ -164,18 +164,16 @@
 	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
 		goto exit;
 
-	if (!(new_client = kmalloc(sizeof(struct i2c_client) +  
-		sizeof(struct w83l785ts_data), GFP_KERNEL))) {
+	if (!(data = kmalloc(sizeof(struct w83l785ts_data), GFP_KERNEL))) {
 		err = -ENOMEM;
 		goto exit;
 	}
-	memset(new_client, 0x00, sizeof(struct i2c_client) +
-	       sizeof(struct w83l785ts_data));
+	memset(data, 0, sizeof(struct w83l785ts_data));
 
 
-	/* The W83L785TS-specific data is placed right after the common I2C
-	 * client data. */
-	data = (struct w83l785ts_data *) (new_client + 1);
+	/* The common I2C client data is placed right before the
+	 * W83L785TS-specific data. */
+	new_client = &data->client;
 	i2c_set_clientdata(new_client, data);
 	new_client->addr = address;
 	new_client->adapter = adapter;
@@ -255,7 +253,7 @@
 	return 0;
 
 exit_free:
-	kfree(new_client);
+	kfree(data);
 exit:
 	return err;
 }
@@ -270,7 +268,7 @@
 		return err;
 	}
 
-	kfree(client);
+	kfree(i2c_get_clientdata(client));
 	return 0;
 }
 
author
#24 lore raw

ChangeSet 1.1643.36.24, 2004/04/12 15:15:36-07:00, [email protected]

[PATCH] I2C: Error paths in it87 and via686a drivers

Here comes the patch that fixes error paths in the it87 and via686a detection functions. The it87 part also adds missing error values.

 drivers/i2c/chips/it87.c    |   33 ++++++++++++++++++---------------
 drivers/i2c/chips/via686a.c |    2 +-
 2 files changed, 19 insertions(+), 16 deletions(-)
drivers/i2c/chips/it87.c +18 -15
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
@@ -533,12 +533,12 @@
 			/* We need the timeouts for at least some IT87-like chips. But only
 			   if we read 'undefined' registers. */
 			i = inb_p(address + 1);
-			if (inb_p(address + 2) != i)
-				goto ERROR1;
-			if (inb_p(address + 3) != i)
-				goto ERROR1;
-			if (inb_p(address + 7) != i)
+			if (inb_p(address + 2) != i
+			 || inb_p(address + 3) != i
+			 || inb_p(address + 7) != i) {
+		 		err = -ENODEV;
 				goto ERROR1;
+			}
 #undef REALLY_SLOW_IO
 
 			/* Let's just hope nothing breaks here */
@@ -546,7 +546,8 @@
 			outb_p(~i & 0x7f, address + 5);
 			if ((inb_p(address + 5) & 0x7f) != (~i & 0x7f)) {
 				outb_p(i, address + 5);
-				return 0;
+				err = -ENODEV;
+				goto ERROR1;
 			}
 		}
 	}
@@ -573,11 +574,12 @@
 	/* Now, we do the remaining detection. */
 
 	if (kind < 0) {
-		if (it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
-			goto ERROR1;
-		if (!is_isa
-			&& (it87_read_value(new_client, IT87_REG_I2C_ADDR) !=
-			address)) goto ERROR1;
+		if ((it87_read_value(new_client, IT87_REG_CONFIG) & 0x80)
+		  || (!is_isa
+		   && it87_read_value(new_client, IT87_REG_I2C_ADDR) != address)) {
+		   	err = -ENODEV;
+			goto ERROR2;
+		}
 	}
 
 	/* Determine the chip type. */
@@ -592,7 +594,8 @@
 					"Ignoring 'force' parameter for unknown chip at "
 					"adapter %d, address 0x%02x\n",
 					i2c_adapter_id(adapter), address);
-			goto ERROR1;
+			err = -ENODEV;
+			goto ERROR2;
 		}
 	}
 
@@ -611,7 +614,7 @@
 
 	/* Tell the I2C layer a new client has arrived */
 	if ((err = i2c_attach_client(new_client)))
-		goto ERROR1;
+		goto ERROR2;
 
 	/* Initialize the IT87 chip */
 	it87_init_client(new_client, data);
@@ -667,9 +670,9 @@
 
 	return 0;
 
-ERROR1:
+ERROR2:
 	kfree(data);
-
+ERROR1:
 	if (is_isa)
 		release_region(address, IT87_EXTENT);
 ERROR0:
drivers/i2c/chips/via686a.c +1 -1
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
@@ -748,9 +748,9 @@
 	return 0;
 
       ERROR3:
-	release_region(address, VIA686A_EXTENT);
 	kfree(data);
       ERROR0:
+	release_region(address, VIA686A_EXTENT);
 	return err;
 }
 
author Applied
#25 lore raw

ChangeSet 1.1643.36.25, 2004/04/12 15:16:08-07:00, [email protected]

[PATCH] I2C: pwm support in w83781d.c

Here is a general pwm support cleanup patch for the w83781d chip driver. Featuring:

* Don't pretend that we handle PWM on AS99127F chips. We don't know how it works, and one of the register we are accessing for now is clearly not a PWM register, and changing its value usually breaks temperature readings.

* Discard irrelevant comments.

* Rewrite show_pwmenable_reg. It was obviously taken from the 2.4 driver, with unneeded tests and the code was much too complicated anyway. And now we handle errors correctly.

* Initialize pwm_enable at load time. So far it was done conditionally (if init=1) while it should always be done. And pwm2_enable wasn't read from the chip, while it should.

I could test that my AS99127F doesn't expose pwm files through ssysfs anymore. Which means that I couldn't test the rest of the pwm changes, unfortunately.

I've applied similar changes to our 2.4/CVS repository.

 drivers/i2c/chips/w83781d.c |   67 +++++++++++++++++---------------------------
 1 files changed, 26 insertions(+), 41 deletions(-)
drivers/i2c/chips/w83781d.c +26 -41
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
@@ -24,7 +24,7 @@
     Supports following chips:
 
     Chip	#vin	#fanin	#pwm	#temp	wchipid	vendid	i2c	ISA
-    as99127f	7	3	1?	3	0x31	0x12c3	yes	no
+    as99127f	7	3	0	3	0x31	0x12c3	yes	no
     as99127f rev.2 (type_name = as99127f)	0x31	0x5ca3	yes	no
     w83781d	7	3	0	3	0x10-1	0x5ca3	yes	yes
     w83627hf	9	3	2	3	0x21	0x5ca3	yes	yes(LPC)
@@ -670,7 +670,6 @@
 device_create_file(&client->dev, &dev_attr_fan##offset##_div); \
 } while (0)
 
-/* w83697hf only has two fans */
 static ssize_t
 show_pwm_reg(struct device *dev, char *buf, int nr)
 {
@@ -678,7 +677,6 @@
 	return sprintf(buf, "%ld\n", (long) PWM_FROM_REG(data->pwm[nr - 1]));
 }
 
-/* w83697hf only has two fans */
 static ssize_t
 show_pwmenable_reg(struct device *dev, char *buf, int nr)
 {
@@ -706,38 +704,26 @@
 {
 	struct i2c_client *client = to_i2c_client(dev);
 	struct w83781d_data *data = i2c_get_clientdata(client);
-	u32 val, j, k;
+	u32 val, reg;
 
 	val = simple_strtoul(buf, NULL, 10);
 
-	/* only PWM2 can be enabled/disabled */
-	if (nr == 2) {
-		j = w83781d_read_value(client, W83781D_REG_PWMCLK12);
-		k = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
-
-		if (val > 0) {
-			if (!(j & 0x08))
-				w83781d_write_value(client,
-						    W83781D_REG_PWMCLK12,
-						    j | 0x08);
-			if (k & 0x10)
-				w83781d_write_value(client,
-						    W83781D_REG_BEEP_CONFIG,
-						    k & 0xef);
+	switch (val) {
+	case 0:
+	case 1:
+		reg = w83781d_read_value(client, W83781D_REG_PWMCLK12);
+		w83781d_write_value(client, W83781D_REG_PWMCLK12,
+				    (reg & 0xf7) | (val << 3));
+
+		reg = w83781d_read_value(client, W83781D_REG_BEEP_CONFIG);
+		w83781d_write_value(client, W83781D_REG_BEEP_CONFIG,
+				    (reg & 0xef) | (!val << 4));
 
-			data->pwmenable[1] = 1;
-		} else {
-			if (j & 0x08)
-				w83781d_write_value(client,
-						    W83781D_REG_PWMCLK12,
-						    j & 0xf7);
-			if (!(k & 0x10))
-				w83781d_write_value(client,
-						    W83781D_REG_BEEP_CONFIG,
-						    j | 0x10);
+		data->pwmenable[nr - 1] = val;
+		break;
 
-			data->pwmenable[1] = 0;
-		}
+	default:
+		return -EINVAL;
 	}
 
 	return count;
@@ -1250,6 +1236,9 @@
 		data->fan_min[i - 1] = w83781d_read_value(new_client,
 					W83781D_REG_FAN_MIN(i));
 	}
+	if (kind != w83781d && kind != as99127f)
+		for (i = 0; i < 4; i++)
+			data->pwmenable[i] = 1;
 
 	/* Register sysfs hooks */
 	device_create_file_in(new_client, 0);
@@ -1290,7 +1279,7 @@
 
 	device_create_file_beep(new_client);
 
-	if (kind != w83781d) {
+	if (kind != w83781d && kind != as99127f) {
 		device_create_file_pwm(new_client, 1);
 		device_create_file_pwm(new_client, 2);
 		device_create_file_pwmenable(new_client, 2);
@@ -1578,9 +1567,6 @@
 			if (!(i & 0x40))
 				w83781d_write_value(client, W83781D_REG_IRQ,
 						    i | 0x40);
-
-			for (i = 0; i < 3; i++)
-				data->pwmenable[i] = 1;
 		}
 	}
 
@@ -1624,20 +1610,19 @@
 			data->fan_min[i - 1] =
 			    w83781d_read_value(client, W83781D_REG_FAN_MIN(i));
 		}
-		if (data->type != w83781d) {
+		if (data->type != w83781d && data->type != as99127f) {
 			for (i = 1; i <= 4; i++) {
 				data->pwm[i - 1] =
 				    w83781d_read_value(client,
 						       W83781D_REG_PWM(i));
-				if (((data->type == w83783s)
-				     || (data->type == w83627hf)
-				     || (data->type == as99127f)
-				     || (data->type == w83697hf)
-				     || ((data->type == w83782d)
-					 && i2c_is_isa_client(client)))
+				if ((data->type != w83782d
+				     || i2c_is_isa_client(client))
 				    && i == 2)
 					break;
 			}
+			/* Only PWM2 can be disabled */
+			data->pwmenable[1] = (w83781d_read_value(client,
+					      W83781D_REG_PWMCLK12) & 0x08) >> 3;
 		}
 
 		data->temp = w83781d_read_value(client, W83781D_REG_TEMP(1));
author
#26 lore raw

ChangeSet 1.1643.36.26, 2004/04/12 15:16:36-07:00, [email protected]

[PATCH] I2C: make I2C chip drivers return -EINVAL on error

 drivers/i2c/chips/fscher.c  |    2 +-
 drivers/i2c/chips/it87.c    |    2 +-
 drivers/i2c/chips/pcf8591.c |    3 ++-
 3 files changed, 4 insertions(+), 3 deletions(-)
drivers/i2c/chips/fscher.c +1 -1
diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
@@ -512,7 +512,7 @@
 	default:
 		dev_err(&client->dev, "fan_div value %ld not "
 			 "supported. Choose one of 2, 4 or 8!\n", v);
-		return -1;
+		return -EINVAL;
 	}
 
 	/* bits 2..7 reserved => mask with 0x03 */
drivers/i2c/chips/it87.c +1 -1
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
@@ -367,7 +367,7 @@
 	else if (val == 2)
 	    data->sensor |= 8 << nr;
 	else if (val != 0)
-		return -1;
+		return -EINVAL;
 	it87_write_value(client, IT87_REG_TEMP_ENABLE, data->sensor);
 	return count;
 }
drivers/i2c/chips/pcf8591.c +2 -1
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
@@ -129,8 +129,9 @@
 	if ((value = (simple_strtoul(buf, NULL, 10) + 5) / 10) <= 255) {
 		data->aout = value;
 		i2c_smbus_write_byte_data(client, data->control, data->aout);
+		return count;
 	}
-	return count;
+	return -EINVAL;
 }
 
 static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, 
author
#27 lore raw

ChangeSet 1.1643.36.27, 2004/04/12 15:17:01-07:00, [email protected]

[PATCH] I2C: fix asb100 bug

Hi nymisi, Greg:

Quoted 11 lines · Nyeste Mihály

Hi!

I reported a bug of asb100 chip at:
http://www2.lm-sensors.nu/~lm78/readticket.cgi?ticket=1539

The reply was the follow:

"Is there a BIOS option you can disable, e.g. Asus "COP", "QFAN", or some such? My guess is that the BIOS is somehow interfering with the asb100 driver. Otherwise I don´t know how this could happen.

^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^

Yeah, I wrote that.

"You do that, you go to the box, you know. Two minutes by yourself, and you feel shame, you know." - Denis the goalie

Greg, please apply this fix (vs. 2.6.5):

 drivers/i2c/chips/asb100.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/chips/asb100.c +1 -1
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
@@ -468,7 +468,7 @@
 		data->reg[nr] = TEMP_TO_REG(val); \
 		break; \
 	} \
-	asb100_write_value(client, ASB100_REG_TEMP_##REG(nr), \
+	asb100_write_value(client, ASB100_REG_TEMP_##REG(nr+1), \
 			data->reg[nr]); \
 	return count; \
 }
author
#28 lore raw

ChangeSet 1.1643.36.28, 2004/04/12 15:17:24-07:00, [email protected]

[PATCH] I2C: Fix voltage rounding in lm80

This one line patch fixes voltage rounding in the lm80 chip driver.

 drivers/i2c/chips/lm80.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/chips/lm80.c +1 -1
diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
@@ -68,7 +68,7 @@
    these macros are called: arguments may be evaluated more than once.
    Fixing this is just not worth it. */
 
-#define IN_TO_REG(val)		(SENSORS_LIMIT((val)/10,0,255))
+#define IN_TO_REG(val)		(SENSORS_LIMIT(((val)+5)/10,0,255))
 #define IN_FROM_REG(val)	((val)*10)
 
 static inline unsigned char FAN_TO_REG(unsigned rpm, unsigned div)
author
#29 lore raw

ChangeSet 1.1643.36.29, 2004/04/12 15:17:46-07:00, [email protected]

[PATCH] I2C: No reset not limit init in via686a

The following patch removes limits initialization in the via686a driver. It was decided some times ago that this belongs to user-space, not kernel. See the thread here:
http://archives.andrew.net.au/lm-sensors/msg06134.html

It also prevents the sensor chip from being savagely reset at load time. This too follows a decision taken long ago that drivers should do as little as possible in their init procedure. See the thread here:
http://archives.andrew.net.au/lm-sensors/msg04593.html

This should make the driver smaller, safer and faster to load. The same was done to our 2.4/CVS version of the driver 5 months ago and it seems to work just fine.

 drivers/i2c/chips/via686a.c |   90 +++-----------------------------------------
 1 files changed, 7 insertions(+), 83 deletions(-)
drivers/i2c/chips/via686a.c +7 -83
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
@@ -329,45 +329,9 @@
 #define DIV_FROM_REG(val) (1 << (val))
 #define DIV_TO_REG(val) ((val)==8?3:(val)==4?2:(val)==1?0:1)
 
-/* Initial limits */
-#define VIA686A_INIT_IN_0 200
-#define VIA686A_INIT_IN_1 250
-#define VIA686A_INIT_IN_2 330
-#define VIA686A_INIT_IN_3 500
-#define VIA686A_INIT_IN_4 1200
-
-#define VIA686A_INIT_IN_PERCENTAGE 10
-
-#define VIA686A_INIT_IN_MIN_0 (VIA686A_INIT_IN_0 - VIA686A_INIT_IN_0 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MAX_0 (VIA686A_INIT_IN_0 + VIA686A_INIT_IN_0 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MIN_1 (VIA686A_INIT_IN_1 - VIA686A_INIT_IN_1 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MAX_1 (VIA686A_INIT_IN_1 + VIA686A_INIT_IN_1 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MIN_2 (VIA686A_INIT_IN_2 - VIA686A_INIT_IN_2 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MAX_2 (VIA686A_INIT_IN_2 + VIA686A_INIT_IN_2 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MIN_3 (VIA686A_INIT_IN_3 - VIA686A_INIT_IN_3 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MAX_3 (VIA686A_INIT_IN_3 + VIA686A_INIT_IN_3 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MIN_4 (VIA686A_INIT_IN_4 - VIA686A_INIT_IN_4 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-#define VIA686A_INIT_IN_MAX_4 (VIA686A_INIT_IN_4 + VIA686A_INIT_IN_4 \
-        * VIA686A_INIT_IN_PERCENTAGE / 100)
-
-#define VIA686A_INIT_FAN_MIN	3000
-
-#define VIA686A_INIT_TEMP_OVER 600
-#define VIA686A_INIT_TEMP_HYST 500
-
-/* For the VIA686A, we need to keep some data in memory. That
-   data is pointed to by via686a_list[NR]->data. The structure itself is
-   dynamically allocated, at the same time when a new via686a client is
-   allocated. */
+/* For the VIA686A, we need to keep some data in memory.
+   The structure is dynamically allocated, at the same time when a new
+   via686a client is allocated. */
 struct via686a_data {
 	struct i2c_client client;
 	struct semaphore update_lock;
@@ -773,53 +737,13 @@
 /* Called when we have found a new VIA686A. Set limits, etc. */
 static void via686a_init_client(struct i2c_client *client)
 {
-	int i;
-
-	/* Reset the device */
-	via686a_write_value(client, VIA686A_REG_CONFIG, 0x80);
-
-	/* Have to wait for reset to complete or else the following
-	   initializations won't work reliably. The delay was arrived at
-	   empirically, the datasheet doesn't tell you.
-	   Waiting for the reset bit to clear doesn't work, it
-	   clears in about 2-4 udelays and that isn't nearly enough. */
-	udelay(50);
-
-	via686a_write_value(client, VIA686A_REG_IN_MIN(0),
-			    IN_TO_REG(VIA686A_INIT_IN_MIN_0, 0));
-	via686a_write_value(client, VIA686A_REG_IN_MAX(0),
-			    IN_TO_REG(VIA686A_INIT_IN_MAX_0, 0));
-	via686a_write_value(client, VIA686A_REG_IN_MIN(1),
-			    IN_TO_REG(VIA686A_INIT_IN_MIN_1, 1));
-	via686a_write_value(client, VIA686A_REG_IN_MAX(1),
-			    IN_TO_REG(VIA686A_INIT_IN_MAX_1, 1));
-	via686a_write_value(client, VIA686A_REG_IN_MIN(2),
-			    IN_TO_REG(VIA686A_INIT_IN_MIN_2, 2));
-	via686a_write_value(client, VIA686A_REG_IN_MAX(2),
-			    IN_TO_REG(VIA686A_INIT_IN_MAX_2, 2));
-	via686a_write_value(client, VIA686A_REG_IN_MIN(3),
-			    IN_TO_REG(VIA686A_INIT_IN_MIN_3, 3));
-	via686a_write_value(client, VIA686A_REG_IN_MAX(3),
-			    IN_TO_REG(VIA686A_INIT_IN_MAX_3, 3));
-	via686a_write_value(client, VIA686A_REG_IN_MIN(4),
-			    IN_TO_REG(VIA686A_INIT_IN_MIN_4, 4));
-	via686a_write_value(client, VIA686A_REG_IN_MAX(4),
-			    IN_TO_REG(VIA686A_INIT_IN_MAX_4, 4));
-	via686a_write_value(client, VIA686A_REG_FAN_MIN(1),
-			    FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
-	via686a_write_value(client, VIA686A_REG_FAN_MIN(2),
-			    FAN_TO_REG(VIA686A_INIT_FAN_MIN, 2));
-	for (i = 0; i <= 2; i++) {
-		via686a_write_value(client, VIA686A_REG_TEMP_OVER(i),
-				    TEMP_TO_REG(VIA686A_INIT_TEMP_OVER));
-		via686a_write_value(client, VIA686A_REG_TEMP_HYST(i),
-				    TEMP_TO_REG(VIA686A_INIT_TEMP_HYST));
-	}
+	u8 reg;
 
 	/* Start monitoring */
-	via686a_write_value(client, VIA686A_REG_CONFIG, 0x01);
+	reg = via686a_read_value(client, VIA686A_REG_CONFIG);
+	via686a_write_value(client, VIA686A_REG_CONFIG, (reg|0x01)&0x7F);
 
-	/* Cofigure temp interrupt mode for continuous-interrupt operation */
+	/* Configure temp interrupt mode for continuous-interrupt operation */
 	via686a_write_value(client, VIA686A_REG_TEMP_MODE, 
 			    via686a_read_value(client, VIA686A_REG_TEMP_MODE) &
 			    !(VIA686A_TEMP_MODE_MASK | VIA686A_TEMP_MODE_CONTINUOUS));
author
#30 lore raw

ChangeSet 1.1643.36.30, 2004/04/14 13:10:38-07:00, [email protected]

[PATCH] I2C: Fix voltage rounding in asb100

This one line patch fixes voltage rounding in the asb100 chip driver. It's very similar to a patch I submitted for the lm80 a few days ago.

 drivers/i2c/chips/asb100.c |    2 +-
 1 files changed, 1 insertion(+), 1 deletion(-)
drivers/i2c/chips/asb100.c +1 -1
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
@@ -124,7 +124,7 @@
 static u8 IN_TO_REG(unsigned val)
 {
 	unsigned nval = SENSORS_LIMIT(val, ASB100_IN_MIN, ASB100_IN_MAX);
-	return nval / 16;
+	return (nval + 8) / 16;
 }
 
 static unsigned IN_FROM_REG(u8 reg)