public inbox for linux-kernel@vger.kernel.org
 help / color / mirror / Atom feed
* [BK PATCH] I2C update for 2.6.5
@ 2004-04-14 22:22 Greg KH
  2004-04-14 22:24 ` [PATCH] " Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:22 UTC (permalink / raw)
  To: torvalds, akpm; +Cc: linux-kernel, sensors

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


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24     ` Greg KH
@ 2004-04-14 22:24       ` Greg KH
  2004-04-14 22:24         ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.4, 2004/03/25 10:51:45-08:00, khali@linux-fr.org

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

Quoting myself:

> 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(+)


diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	Wed Apr 14 15:14:44 2004
+++ b/drivers/i2c/chips/asb100.c	Wed Apr 14 15:14:44 2004
@@ -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);
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	Wed Apr 14 15:14:44 2004
+++ b/drivers/i2c/chips/lm78.c	Wed Apr 14 15:14:44 2004
@@ -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);
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:14:44 2004
+++ b/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:14:44 2004
@@ -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)


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24   ` Greg KH
@ 2004-04-14 22:24     ` Greg KH
  2004-04-14 22:24       ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.3, 2004/03/25 10:50:47-08:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:14:49 2004
+++ b/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:14:49 2004
@@ -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)	\


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24       ` Greg KH
@ 2004-04-14 22:24         ` Greg KH
  2004-04-14 22:24           ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.5, 2004/03/26 13:52:39-08:00, khali@linux-fr.org

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

Quoting myself:

> 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(-)


diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:14:38 2004
+++ b/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:14:38 2004
@@ -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);
 }


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24 ` [PATCH] " Greg KH
@ 2004-04-14 22:24   ` Greg KH
  2004-04-14 22:24     ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.2, 2004/03/19 13:24:39-08:00, aurelien@aurel32.net

[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(+)


diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	Wed Apr 14 15:14:55 2004
+++ b/drivers/i2c/chips/Kconfig	Wed Apr 14 15:14:55 2004
@@ -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
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	Wed Apr 14 15:14:55 2004
+++ b/drivers/i2c/chips/Makefile	Wed Apr 14 15:14:55 2004
@@ -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
 
diff -Nru a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/pcf8574.c	Wed Apr 14 15:14:55 2004
@@ -0,0 +1,245 @@
+/*
+    pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware
+             monitoring
+    Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, 
+                        Philip Edelbrock <phil@netroedge.com>,
+                        Dan Eaton <dan.eaton@rocketlogix.com>
+    Ported to Linux 2.6 by Aurelien Jarno <aurel32@debian.org> with 
+    the help of Jean Delvare <khali@linux-fr.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+    
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/* A few notes about the PCF8574:
+
+* The PCF8574 is an 8-bit I/O expander for the I2C bus produced by
+  Philips Semiconductors.  It is designed to provide a byte I2C
+  interface to up to 8 separate devices.
+  
+* The PCF8574 appears as a very simple SMBus device which can be
+  read from or written to with SMBUS byte read/write accesses.
+
+  --Dan
+
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { 0x20, 0x27, 0x38, 0x3f, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_2(pcf8574, pcf8574a);
+
+/* Initial values */
+#define PCF8574_INIT 255	/* All outputs on (input mode) */
+
+/* Each client has this additional data */
+struct pcf8574_data {
+	struct semaphore update_lock;
+
+	u8 read, write;			/* Register values */
+};
+
+static int pcf8574_attach_adapter(struct i2c_adapter *adapter);
+static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pcf8574_detach_client(struct i2c_client *client);
+static void pcf8574_init_client(struct i2c_client *client);
+static struct pcf8574_data *pcf8574_update_client(struct device *dev);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pcf8574_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "pcf8574",
+	.id		= I2C_DRIVERID_PCF8574,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= pcf8574_attach_adapter,
+	.detach_client	= pcf8574_detach_client,
+};
+
+static int pcf8574_id = 0;
+
+/* following are the sysfs callback functions */
+static ssize_t show_read(struct device *dev, char *buf)
+{
+	struct pcf8574_data *data = pcf8574_update_client(dev);
+	return sprintf(buf, "%u\n", data->read);
+}
+
+static DEVICE_ATTR(read, S_IRUGO, show_read, NULL);
+
+static ssize_t show_write(struct device *dev, char *buf)
+{
+	struct pcf8574_data *data = i2c_get_clientdata(to_i2c_client(dev));
+	return sprintf(buf, "%u\n", data->write);
+}
+
+static ssize_t set_write(struct device *dev, const char *buf,
+			 size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf8574_data *data = i2c_get_clientdata(client);
+	data->write = simple_strtoul(buf, NULL, 10);
+	i2c_smbus_write_byte(client, data->write);
+	return count;
+}
+
+static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
+
+/*
+ * Real code
+ */
+
+static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, pcf8574_detect);
+}
+
+/* This function is called by i2c_detect */
+int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct pcf8574_data *data;
+	int err = 0;
+	const char *client_name = "";
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet. */
+	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+				   sizeof(struct pcf8574_data),
+				   GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	memset(new_client, 0, sizeof(struct i2c_client) +
+	       sizeof(struct pcf8574_data));
+
+	data = (struct pcf8574_data *) (new_client + 1);
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &pcf8574_driver;
+	new_client->flags = 0;
+
+	/* Now, we would do the remaining detection. But the PCF8574 is plainly
+	   impossible to detect! Stupid chip. */
+
+	/* Determine the chip type */
+	if (kind <= 0) {
+		if (address >= 0x38 && address <= 0x3f)
+			kind = pcf8574a;
+		else
+			kind = pcf8574;
+	}
+
+	if (kind == pcf8574a)
+		client_name = "pcf8574a";
+	else
+		client_name = "pcf8574";
+
+	/* Fill in the remaining client fields and put it into the global list */
+	strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+
+	new_client->id = pcf8574_id++;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_free;
+	
+	/* Initialize the PCF8574 chip */
+	pcf8574_init_client(new_client);
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_read);
+	device_create_file(&new_client->dev, &dev_attr_write);
+	return 0;
+
+/* OK, this is not exactly good programming practice, usually. But it is
+   very code-efficient in this case. */
+
+      exit_free:
+	kfree(new_client);
+      exit:
+	return err;
+}
+
+static int pcf8574_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev,
+			"Client deregistration failed, client not detached.\n");
+		return err;
+	}
+
+	kfree(client);
+	return 0;
+}
+
+/* Called when we have found a new PCF8574. */
+static void pcf8574_init_client(struct i2c_client *client)
+{
+	struct pcf8574_data *data = i2c_get_clientdata(client);
+	data->write = PCF8574_INIT;
+	i2c_smbus_write_byte(client, data->write);
+}
+
+static struct pcf8574_data *pcf8574_update_client(struct device *dev)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf8574_data *data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+	dev_dbg(&client->dev, "Starting pcf8574 update\n");
+	data->read = i2c_smbus_read_byte(client); 
+	up(&data->update_lock);
+	
+	return data;
+}
+
+static int __init pcf8574_init(void)
+{
+	return i2c_add_driver(&pcf8574_driver);
+}
+
+static void __exit pcf8574_exit(void)
+{
+	i2c_del_driver(&pcf8574_driver);
+}
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, "
+     "Philip Edelbrock <phil@netroedge.com>, "
+     "Dan Eaton <dan.eaton@rocketlogix.com> "
+     "and Aurelien Jarno <aurelien@aurel32.net>");
+MODULE_DESCRIPTION("PCF8574 driver");
+MODULE_LICENSE("GPL");
+
+module_init(pcf8574_init);
+module_exit(pcf8574_exit);


^ permalink raw reply	[flat|nested] 31+ messages in thread

* [PATCH] I2C update for 2.6.5
  2004-04-14 22:22 [BK PATCH] I2C update for 2.6.5 Greg KH
@ 2004-04-14 22:24 ` Greg KH
  2004-04-14 22:24   ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.1, 2004/03/19 13:24:14-08:00, khali@linux-fr.org

[PATCH] I2C: w83781d fan_div code refactoring

Quoting myself:

> 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(-)


diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:15:00 2004
+++ b/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:15:00 2004
@@ -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)
 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                 ` Greg KH
@ 2004-04-14 22:24                   ` Greg KH
  2004-04-14 22:24                     ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.10, 2004/03/30 14:27:06-08:00, khali@linux-fr.org

[PATCH] I2C: Incorrect memset in eeprom.c

Quoting Ralf Roesch:

> 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(-)


diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
--- a/drivers/i2c/chips/eeprom.c	Wed Apr 14 15:14:11 2004
+++ b/drivers/i2c/chips/eeprom.c	Wed Apr 14 15:14:11 2004
@@ -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;


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24         ` Greg KH
@ 2004-04-14 22:24           ` Greg KH
  2004-04-14 22:24             ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.6, 2004/03/26 13:53:01-08:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c	Wed Apr 14 15:14:33 2004
+++ b/drivers/i2c/chips/w83627hf.c	Wed Apr 14 15:14:33 2004
@@ -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);


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                   ` Greg KH
@ 2004-04-14 22:24                     ` Greg KH
  2004-04-14 22:24                       ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.11, 2004/03/30 14:27:21-08:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	Wed Apr 14 15:14:05 2004
+++ b/drivers/i2c/chips/via686a.c	Wed Apr 14 15:14:05 2004
@@ -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.
 */
 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24             ` Greg KH
@ 2004-04-14 22:24               ` Greg KH
  2004-04-14 22:24                 ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.8, 2004/03/30 14:26:38-08:00, khali@linux-fr.org

[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(-)


diff -Nru a/Documentation/i2c/porting-clients b/Documentation/i2c/porting-clients
--- a/Documentation/i2c/porting-clients	Wed Apr 14 15:14:22 2004
+++ b/Documentation/i2c/porting-clients	Wed Apr 14 15:14:22 2004
@@ -1,4 +1,4 @@
-Revision 3, 2003-10-04
+Revision 4, 2004-03-30
 Jean Delvare <khali@linux-fr.org>
 Greg KH <greg@kroah.com>
 
@@ -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.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24           ` Greg KH
@ 2004-04-14 22:24             ` Greg KH
  2004-04-14 22:24               ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.7, 2004/03/30 14:26:19-08:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:14:28 2004
+++ b/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:14:28 2004
@@ -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);


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                     ` Greg KH
@ 2004-04-14 22:24                       ` Greg KH
  2004-04-14 22:24                         ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.12, 2004/04/02 11:02:14-08:00, mochel@digitalimplant.org

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


 include/linux/pci_ids.h |    1 +
 1 files changed, 1 insertion(+)


diff -Nru a/include/linux/pci_ids.h b/include/linux/pci_ids.h
--- a/include/linux/pci_ids.h	Wed Apr 14 15:14:00 2004
+++ b/include/linux/pci_ids.h	Wed Apr 14 15:14:00 2004
@@ -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


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24               ` Greg KH
@ 2004-04-14 22:24                 ` Greg KH
  2004-04-14 22:24                   ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.9, 2004/03/30 14:26:52-08:00, khali@linux-fr.org

[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(-)


diff -Nru a/Documentation/i2c/sysfs-interface b/Documentation/i2c/sysfs-interface
--- a/Documentation/i2c/sysfs-interface	Wed Apr 14 15:14:16 2004
+++ b/Documentation/i2c/sysfs-interface	Wed Apr 14 15:14:16 2004
@@ -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.


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                         ` Greg KH
@ 2004-04-14 22:24                           ` Greg KH
  2004-04-14 22:24                             ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.14, 2004/04/02 11:03:04-08:00, mochel@digitalimplant.org

[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(+)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Wed Apr 14 15:13:49 2004
+++ b/drivers/i2c/busses/Kconfig	Wed Apr 14 15:13:49 2004
@@ -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
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Wed Apr 14 15:13:49 2004
+++ b/drivers/i2c/busses/Makefile	Wed Apr 14 15:13:49 2004
@@ -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
diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:49 2004
@@ -0,0 +1,421 @@
+/**
+ *	i2c-ali1563.c - i2c driver for the ALi 1563 Southbridge
+ *
+ *	Copyright (C) 2004 Patrick Mochel
+ *
+ *	The 1563 southbridge is deceptively similar to the 1533, with a
+ *	few notable exceptions. One of those happens to be the fact they
+ *	upgraded the i2c core to be 2.0 compliant, and happens to be almost
+ *	identical to the i2c controller found in the Intel 801 south
+ *	bridges.
+ *
+ *	This driver is based on a mix of the 15x3, 1535, and i801 drivers,
+ *	with a little help from the ALi 1563 spec.
+ *
+ *	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>
+#include <linux/init.h>
+
+#define ALI1563_MAX_TIMEOUT	500
+#define	ALI1563_SMBBA		0x80
+#define ALI1563_SMB_IOEN	1
+#define ALI1563_SMB_HOSTEN	2
+#define ALI1563_SMB_IOSIZE	16
+
+#define SMB_HST_STS	(ali1563_smba + 0)
+#define SMB_HST_CNTL1	(ali1563_smba + 1)
+#define SMB_HST_CNTL2	(ali1563_smba + 2)
+#define SMB_HST_CMD	(ali1563_smba + 3)
+#define SMB_HST_ADD	(ali1563_smba + 4)
+#define SMB_HST_DAT0	(ali1563_smba + 5)
+#define SMB_HST_DAT1	(ali1563_smba + 6)
+#define SMB_BLK_DAT	(ali1563_smba + 7)
+
+#define HST_STS_BUSY	0x01
+#define HST_STS_INTR	0x02
+#define HST_STS_DEVERR	0x04
+#define HST_STS_BUSERR	0x08
+#define HST_STS_FAIL	0x10
+#define HST_STS_DONE	0x80
+#define HST_STS_BAD	0x1c
+
+
+#define HST_CNTL1_TIMEOUT	0x80
+#define HST_CNTL1_LAST		0x40
+
+#define HST_CNTL2_KILL		0x04
+#define HST_CNTL2_START		0x40
+#define HST_CNTL2_QUICK		0x00
+#define HST_CNTL2_BYTE		0x01
+#define HST_CNTL2_BYTE_DATA	0x02
+#define HST_CNTL2_WORD_DATA	0x03
+#define HST_CNTL2_BLOCK		0x05
+
+
+
+static unsigned short ali1563_smba;
+
+static int ali1563_transaction(struct i2c_adapter * a)
+{
+	u32 data;
+	int timeout;
+
+	dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
+		"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
+		inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
+		inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
+		inb_p(SMB_HST_DAT1));
+
+	data = inb_p(SMB_HST_STS);
+	if (data & HST_STS_BAD) {
+		dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
+		outb_p(data | HST_STS_BAD,SMB_HST_STS);
+		data = inb_p(SMB_HST_STS);
+		if (data & HST_STS_BAD)
+			return -EBUSY;
+	}
+	outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2);
+
+	timeout = ALI1563_MAX_TIMEOUT;
+	do
+		i2c_delay(1);
+	while (((data = inb_p(SMB_HST_STS)) & HST_STS_BUSY) && --timeout);
+
+	dev_dbg(&a->dev, "Transaction (post): STS=%02x, CNTL1=%02x, "
+		"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
+		inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
+		inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
+		inb_p(SMB_HST_DAT1));
+
+	if (timeout && !(data & HST_STS_BAD))
+		return 0;
+	dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
+		timeout ? "Timeout " : "",
+		data & HST_STS_FAIL ? "Transaction Failed " : "",
+		data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
+		data & HST_STS_DEVERR ? "Device Error " : "",
+		!(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
+
+	if (!(data & HST_STS_DONE))
+		/* Issue 'kill' to host controller */
+		outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
+	else
+		/* Issue timeout to reset all devices on bus */
+		outb_p(HST_CNTL1_TIMEOUT,SMB_HST_CNTL1);
+	return -1;
+}
+
+static int ali1563_block_start(struct i2c_adapter * a)
+{
+	u32 data;
+	int timeout;
+
+	dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
+		"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
+		inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
+		inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
+		inb_p(SMB_HST_DAT1));
+
+	data = inb_p(SMB_HST_STS);
+	if (data & HST_STS_BAD) {
+		dev_warn(&a->dev,"ali1563: Trying to reset busy device\n");
+		outb_p(data | HST_STS_BAD,SMB_HST_STS);
+		data = inb_p(SMB_HST_STS);
+		if (data & HST_STS_BAD)
+			return -EBUSY;
+	}
+
+	/* Clear byte-ready bit */
+	outb_p(data | HST_STS_DONE, SMB_HST_STS);
+
+	/* Start transaction and wait for byte-ready bit to be set */
+	outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_START, SMB_HST_CNTL2);
+
+	timeout = ALI1563_MAX_TIMEOUT;
+	do
+		i2c_delay(1);
+	while (!((data = inb_p(SMB_HST_STS)) & HST_STS_DONE) && --timeout);
+
+	dev_dbg(&a->dev, "Block (post): STS=%02x, CNTL1=%02x, "
+		"CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
+		inb_p(SMB_HST_STS), inb_p(SMB_HST_CNTL1), inb_p(SMB_HST_CNTL2),
+		inb_p(SMB_HST_CMD), inb_p(SMB_HST_ADD), inb_p(SMB_HST_DAT0),
+		inb_p(SMB_HST_DAT1));
+
+	if (timeout && !(data & HST_STS_BAD))
+		return 0;
+	dev_warn(&a->dev, "SMBus Error: %s%s%s%s%s\n",
+		timeout ? "Timeout " : "",
+		data & HST_STS_FAIL ? "Transaction Failed " : "",
+		data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
+		data & HST_STS_DEVERR ? "Device Error " : "",
+		!(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
+	return -1;
+}
+
+static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
+{
+	int i, len;
+	int error = 0;
+
+	/* Do we need this? */
+	outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
+
+	if (rw == I2C_SMBUS_WRITE) {
+		len = data->block[0];
+		if (len < 1)
+			len = 1;
+		else if (len > 32)
+			len = 32;
+		outb_p(len,SMB_HST_DAT0);
+		outb_p(data->block[1],SMB_BLK_DAT);
+	} else
+		len = 32;
+
+	outb_p(inb_p(SMB_HST_CNTL2) | HST_CNTL2_BLOCK, SMB_HST_CNTL2);
+
+	for (i = 0; i < len; i++) {
+		if (rw == I2C_SMBUS_WRITE) {
+			outb_p(data->block[i + 1], SMB_BLK_DAT);
+			if ((error = ali1563_block_start(a)))
+				break;
+		} else {
+			if ((error = ali1563_block_start(a)))
+				break;
+			if (i == 0) {
+				len = inb_p(SMB_HST_DAT0);
+				if (len < 1)
+					len = 1;
+				else if (len > 32)
+					len = 32;
+			}
+			data->block[i+1] = inb_p(SMB_BLK_DAT);
+		}
+	}
+	/* Do we need this? */
+	outb_p(HST_CNTL1_LAST,SMB_HST_CNTL1);
+	return error;
+}
+
+static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
+			  unsigned short flags, char rw, u8 cmd,
+			  int size, union i2c_smbus_data * data)
+{
+	int error = 0;
+	int timeout;
+	u32 reg;
+
+	for (timeout = ALI1563_MAX_TIMEOUT; timeout; timeout--) {
+		if (!(reg = inb_p(SMB_HST_STS) & HST_STS_BUSY))
+			break;
+	}
+	if (!timeout)
+		dev_warn(&a->dev,"SMBus not idle. HST_STS = %02x\n",reg);
+	outb_p(0xff,SMB_HST_STS);
+
+	/* Map the size to what the chip understands */
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
+		error = -EINVAL;
+		break;
+	case I2C_SMBUS_QUICK:
+		size = HST_CNTL2_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		size = HST_CNTL2_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		size = HST_CNTL2_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		size = HST_CNTL2_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		size = HST_CNTL2_BLOCK;
+		break;
+	}
+
+	outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
+	outb_p(inb_p(SMB_HST_CNTL2) | (size << 3), SMB_HST_CNTL2);
+
+	/* Write the command register */
+	switch(size) {
+	case HST_CNTL2_BYTE:
+		if (rw== I2C_SMBUS_WRITE)
+			outb_p(cmd, SMB_HST_CMD);
+		break;
+	case HST_CNTL2_BYTE_DATA:
+		outb_p(cmd, SMB_HST_CMD);
+		if (rw == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMB_HST_DAT0);
+		break;
+	case HST_CNTL2_WORD_DATA:
+		outb_p(cmd, SMB_HST_CMD);
+		if (rw == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMB_HST_DAT0);
+			outb_p((data->word & 0xff00) >> 8, SMB_HST_DAT1);
+		}
+		break;
+	case HST_CNTL2_BLOCK:
+		outb_p(cmd, SMB_HST_CMD);
+		error = ali1563_block(a,data,rw);
+		goto Done;
+	}
+
+	if ((error = ali1563_transaction(a)))
+		goto Done;
+
+	if ((rw == I2C_SMBUS_WRITE) || (size == HST_CNTL2_QUICK))
+		goto Done;
+
+	switch (size) {
+	case HST_CNTL2_BYTE:	/* Result put in SMBHSTDAT0 */
+		data->byte = inb_p(SMB_HST_DAT0);
+		break;
+	case HST_CNTL2_BYTE_DATA:
+		data->byte = inb_p(SMB_HST_DAT0);
+		break;
+	case HST_CNTL2_WORD_DATA:
+		data->word = inb_p(SMB_HST_DAT0) + (inb_p(SMB_HST_DAT1) << 8);
+		break;
+	}
+Done:
+	return error;
+}
+
+static u32 ali1563_func(struct i2c_adapter * a)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+
+static void ali1563_enable(struct pci_dev * dev)
+{
+	u16 ctrl;
+
+	pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
+	ctrl |= 0x7;
+	pci_write_config_word(dev,ALI1563_SMBBA,ctrl);
+}
+
+static int __init ali1563_setup(struct pci_dev * dev)
+{
+	u16 ctrl;
+
+	pci_read_config_word(dev,ALI1563_SMBBA,&ctrl);
+	printk("ali1563: SMBus control = %04x\n",ctrl);
+
+	/* Check if device is even enabled first */
+	if (!(ctrl & ALI1563_SMB_IOEN)) {
+		dev_warn(&dev->dev,"I/O space not enabled, trying manually\n");
+		ali1563_enable(dev);
+	}
+	if (!(ctrl & ALI1563_SMB_IOEN)) {
+		dev_warn(&dev->dev,"I/O space still not enabled, giving up\n");
+		goto Err;
+	}
+	if (!(ctrl & ALI1563_SMB_HOSTEN)) {
+		dev_warn(&dev->dev,"Host Controller not enabled\n");
+		goto Err;
+	}
+
+	/* SMB I/O Base in high 12 bits and must be aligned with the
+	 * size of the I/O space. */
+	ali1563_smba = ctrl & ~(ALI1563_SMB_IOSIZE - 1);
+	if (!ali1563_smba) {
+		dev_warn(&dev->dev,"ali1563_smba Uninitialized\n");
+		goto Err;
+	}
+	if (!request_region(ali1563_smba,ALI1563_SMB_IOSIZE,"i2c-ali1563")) {
+		dev_warn(&dev->dev,"Could not allocate I/O space");
+		goto Err;
+	}
+
+	return 0;
+Err:
+	return -ENODEV;
+}
+
+static void __exit ali1563_shutdown(struct pci_dev * dev)
+{
+	release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
+}
+
+static struct i2c_algorithm ali1563_algorithm = {
+	.name		= "Non-i2c SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= ali1563_access,
+	.functionality	= ali1563_func,
+};
+
+static struct i2c_adapter ali1563_adapter = {
+	.owner	= THIS_MODULE,
+	.algo	= &ali1563_algorithm,
+};
+
+static int __init ali1563_probe(struct pci_dev * dev,
+				const struct pci_device_id * id_table)
+{
+	int error;
+
+	if ((error = ali1563_setup(dev)))
+		return error;
+	ali1563_adapter.dev.parent = &dev->dev;
+	sprintf(ali1563_adapter.name,"SMBus ALi 1563 Adapter @ %04x",
+		ali1563_smba);
+	if ((error = i2c_add_adapter(&ali1563_adapter)))
+		ali1563_shutdown(dev);
+	printk("%s: Returning %d\n",__FUNCTION__,error);
+	return error;
+}
+
+static void __exit ali1563_remove(struct pci_dev * dev)
+{
+	i2c_del_adapter(&ali1563_adapter);
+	ali1563_shutdown(dev);
+}
+
+static struct pci_device_id __devinitdata ali1563_id_table[] = {
+	{
+		.vendor		= PCI_VENDOR_ID_AL,
+		.device		= PCI_DEVICE_ID_AL_M1563,
+		.subvendor	= PCI_ANY_ID,
+		.subdevice	= PCI_ANY_ID,
+	},
+	{},
+};
+
+static struct pci_driver ali1563_pci_driver = {
+ 	.name		= "i2c-ali1563",
+	.id_table	= ali1563_id_table,
+ 	.probe		= ali1563_probe,
+	.remove		= ali1563_remove,
+};
+
+static int __init ali1563_init(void)
+{
+	return pci_module_init(&ali1563_pci_driver);
+}
+
+module_init(ali1563_init);
+
+static void __exit ali1563_exit(void)
+{
+	pci_unregister_driver(&ali1563_pci_driver);
+}
+
+module_exit(ali1563_exit);
+
+MODULE_LICENSE("GPL");


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                       ` Greg KH
@ 2004-04-14 22:24                         ` Greg KH
  2004-04-14 22:24                           ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.13, 2004/04/02 11:02:40-08:00, mochel@digitalimplant.org

[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(-)


diff -Nru a/arch/i386/pci/irq.c b/arch/i386/pci/irq.c
--- a/arch/i386/pci/irq.c	Wed Apr 14 15:13:55 2004
+++ b/arch/i386/pci/irq.c	Wed Apr 14 15:13:55 2004
@@ -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;
 }


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                           ` Greg KH
@ 2004-04-14 22:24                             ` Greg KH
  2004-04-14 22:24                               ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.15, 2004/04/02 11:05:14-08:00, mochel@digitalimplant.org

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


 drivers/i2c/busses/i2c-ali1563.c |    5 -----
 1 files changed, 5 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:44 2004
+++ b/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:44 2004
@@ -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>


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                 ` Greg KH
@ 2004-04-14 22:24                                   ` Greg KH
  2004-04-14 22:24                                     ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.18, 2004/04/08 14:12:39-07:00, akpm@osdl.org

[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(-)


diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:27 2004
+++ b/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:27 2004
@@ -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);
 }


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                             ` Greg KH
@ 2004-04-14 22:24                               ` Greg KH
  2004-04-14 22:24                                 ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.16, 2004/04/08 10:23:27-07:00, khali@linux-fr.org

[PATCH] I2C: Refactor swap_bytes in i2c chip drivers

> 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(-)


diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	Wed Apr 14 15:13:38 2004
+++ b/drivers/i2c/chips/asb100.c	Wed Apr 14 15:13:38 2004
@@ -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;
 		}
 	}
diff -Nru a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
--- a/drivers/i2c/chips/ds1621.c	Wed Apr 14 15:13:38 2004
+++ b/drivers/i2c/chips/ds1621.c	Wed Apr 14 15:13:38 2004
@@ -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)
diff -Nru a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
--- a/drivers/i2c/chips/gl518sm.c	Wed Apr 14 15:13:38 2004
+++ b/drivers/i2c/chips/gl518sm.c	Wed Apr 14 15:13:38 2004
@@ -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);
 }
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c	Wed Apr 14 15:13:38 2004
+++ b/drivers/i2c/chips/lm75.c	Wed Apr 14 15:13:38 2004
@@ -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)
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:13:38 2004
+++ b/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:13:38 2004
@@ -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;
 			}
 		}


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                               ` Greg KH
@ 2004-04-14 22:24                                 ` Greg KH
  2004-04-14 22:24                                   ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.17, 2004/04/08 14:12:22-07:00, mochel@digitalimplant.org

[PATCH] I2C: class fixup for the ali1563 driver


 drivers/i2c/busses/i2c-ali1563.c |    1 +
 1 files changed, 1 insertion(+)


diff -Nru a/drivers/i2c/busses/i2c-ali1563.c b/drivers/i2c/busses/i2c-ali1563.c
--- a/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:33 2004
+++ b/drivers/i2c/busses/i2c-ali1563.c	Wed Apr 14 15:13:33 2004
@@ -357,6 +357,7 @@
 
 static struct i2c_adapter ali1563_adapter = {
 	.owner	= THIS_MODULE,
+	.class	= I2C_ADAP_CLASS_SMBUS,
 	.algo	= &ali1563_algorithm,
 };
 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                   ` Greg KH
@ 2004-04-14 22:24                                     ` Greg KH
  2004-04-14 22:24                                       ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.19, 2004/04/09 11:58:21-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
--- a/drivers/i2c/chips/lm80.c	Wed Apr 14 15:13:22 2004
+++ b/drivers/i2c/chips/lm80.c	Wed Apr 14 15:13:22 2004
@@ -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) |


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                     ` Greg KH
@ 2004-04-14 22:24                                       ` Greg KH
  2004-04-14 22:24                                         ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.20, 2004/04/09 12:05:44-07:00, aurelien@aurel32.net

[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(-)


diff -Nru a/drivers/i2c/chips/Kconfig b/drivers/i2c/chips/Kconfig
--- a/drivers/i2c/chips/Kconfig	Wed Apr 14 15:13:16 2004
+++ b/drivers/i2c/chips/Kconfig	Wed Apr 14 15:13:16 2004
@@ -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
diff -Nru a/drivers/i2c/chips/Makefile b/drivers/i2c/chips/Makefile
--- a/drivers/i2c/chips/Makefile	Wed Apr 14 15:13:16 2004
+++ b/drivers/i2c/chips/Makefile	Wed Apr 14 15:13:16 2004
@@ -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
 
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:13:17 2004
@@ -0,0 +1,321 @@
+/*
+    pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware
+                monitoring
+    Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
+    Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with 
+    the help of Jean Delvare <khali@linux-fr.org>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation; either version 2 of the License, or
+    (at your option) any later version.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+#include <linux/module.h>
+#include <linux/init.h>
+#include <linux/slab.h>
+#include <linux/i2c.h>
+#include <linux/i2c-sensor.h>
+
+/* Addresses to scan */
+static unsigned short normal_i2c[] = { I2C_CLIENT_END };
+static unsigned short normal_i2c_range[] = { 0x48, 0x4f, I2C_CLIENT_END };
+static unsigned int normal_isa[] = { I2C_CLIENT_ISA_END };
+static unsigned int normal_isa_range[] = { I2C_CLIENT_ISA_END };
+
+/* Insmod parameters */
+SENSORS_INSMOD_1(pcf8591);
+
+static int input_mode;
+MODULE_PARM(input_mode, "i");
+MODULE_PARM_DESC(input_mode,
+	"Analog input mode:\n"
+	" 0 = four single ended inputs\n"
+	" 1 = three differential inputs\n"
+	" 2 = single ended and differential mixed\n"
+	" 3 = two differential inputs\n");
+
+/* The PCF8591 control byte
+      7    6    5    4    3    2    1    0  
+   |  0 |AOEF|   AIP   |  0 |AINC|  AICH   | */
+
+/* Analog Output Enable Flag (analog output active if 1) */
+#define PCF8591_CONTROL_AOEF		0x40
+					
+/* Analog Input Programming 
+   0x00 = four single ended inputs
+   0x10 = three differential inputs
+   0x20 = single ended and differential mixed
+   0x30 = two differential inputs */
+#define PCF8591_CONTROL_AIP_MASK	0x30
+
+/* Autoincrement Flag (switch on if 1) */
+#define PCF8591_CONTROL_AINC		0x04
+
+/* Channel selection
+   0x00 = channel 0 
+   0x01 = channel 1
+   0x02 = channel 2
+   0x03 = channel 3 */
+#define PCF8591_CONTROL_AICH_MASK	0x03
+
+/* Initial values */
+#define PCF8591_INIT_CONTROL	((input_mode << 4) | PCF8591_CONTROL_AOEF)
+#define PCF8591_INIT_AOUT	0	/* DAC out = 0 */
+
+/* Conversions */
+#define REG_TO_SIGNED(reg)	(((reg) & 0x80)?((reg) - 256):(reg))
+
+struct pcf8591_data {
+	struct semaphore update_lock;
+
+	u8 control;
+	u8 aout;
+};
+
+static int pcf8591_attach_adapter(struct i2c_adapter *adapter);
+static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind);
+static int pcf8591_detach_client(struct i2c_client *client);
+static void pcf8591_init_client(struct i2c_client *client);
+static int pcf8591_read_channel(struct device *dev, int channel);
+
+/* This is the driver that will be inserted */
+static struct i2c_driver pcf8591_driver = {
+	.owner		= THIS_MODULE,
+	.name		= "pcf8591",
+	.id		= I2C_DRIVERID_PCF8591,
+	.flags		= I2C_DF_NOTIFY,
+	.attach_adapter	= pcf8591_attach_adapter,
+	.detach_client	= pcf8591_detach_client,
+};
+
+static int pcf8591_id = 0;
+
+/* following are the sysfs callback functions */
+#define show_in_channel(channel)					\
+static ssize_t show_in##channel##_input(struct device *dev, char *buf)	\
+{									\
+	return sprintf(buf, "%d\n", pcf8591_read_channel(dev, channel));\
+}									\
+static DEVICE_ATTR(in##channel##_input, S_IRUGO,			\
+		   show_in##channel##_input, NULL);
+
+show_in_channel(0);
+show_in_channel(1);
+show_in_channel(2);
+show_in_channel(3);
+
+static ssize_t show_out0_ouput(struct device *dev, char *buf)
+{
+	struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
+	return sprintf(buf, "%d\n", data->aout * 10);
+}
+
+static ssize_t set_out0_output(struct device *dev, const char *buf, size_t count)
+{
+	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);
+	{
+		data->aout = value;
+		i2c_smbus_write_byte_data(client, data->control, data->aout);
+	}
+	return count;
+}
+
+static DEVICE_ATTR(out0_output, S_IWUSR | S_IRUGO, 
+		   show_out0_ouput, set_out0_output);
+
+static ssize_t show_out0_enable(struct device *dev, char *buf)
+{
+	struct pcf8591_data *data = i2c_get_clientdata(to_i2c_client(dev));
+	return sprintf(buf, "%u\n", !(!(data->control & PCF8591_CONTROL_AOEF)));
+}
+
+static ssize_t set_out0_enable(struct device *dev, const char *buf, size_t count)
+{
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf8591_data *data = i2c_get_clientdata(client);
+	if (simple_strtoul(buf, NULL, 10))
+		data->control |= PCF8591_CONTROL_AOEF;
+	else
+		data->control &= ~PCF8591_CONTROL_AOEF;
+	i2c_smbus_write_byte(client, data->control);
+	return count;
+}
+
+static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 
+		   show_out0_enable, set_out0_enable);
+
+/*
+ * Real code
+ */
+static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
+{
+	return i2c_detect(adapter, &addr_data, pcf8591_detect);
+}
+
+/* This function is called by i2c_detect */
+int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
+{
+	struct i2c_client *new_client;
+	struct pcf8591_data *data;
+	int err = 0;
+
+	if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE
+				     | I2C_FUNC_SMBUS_WRITE_BYTE_DATA))
+		goto exit;
+
+	/* OK. For now, we presume we have a valid client. We now create the
+	   client structure, even though we cannot fill it completely yet. */
+	if (!(new_client = kmalloc(sizeof(struct i2c_client) +
+				   sizeof(struct pcf8591_data),
+				   GFP_KERNEL))) {
+		err = -ENOMEM;
+		goto exit;
+	}
+
+	memset(new_client, 0, sizeof(struct i2c_client) +
+			      sizeof(struct pcf8591_data));
+	
+	data = (struct pcf8591_data *) (new_client + 1);
+	i2c_set_clientdata(new_client, data);
+	new_client->addr = address;
+	new_client->adapter = adapter;
+	new_client->driver = &pcf8591_driver;
+	new_client->flags = 0;
+
+	/* Now, we would do the remaining detection. But the PCF8591 is plainly
+	   impossible to detect! Stupid chip. */
+
+	/* Determine the chip type - only one kind supported! */
+	if (kind <= 0)
+		kind = pcf8591;
+
+	/* Fill in the remaining client fields and put it into the global 
+	   list */
+	strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
+
+	new_client->id = pcf8591_id++;
+	init_MUTEX(&data->update_lock);
+
+	/* Tell the I2C layer a new client has arrived */
+	if ((err = i2c_attach_client(new_client)))
+		goto exit_kfree;
+
+	/* Initialize the PCF8591 chip */
+	pcf8591_init_client(new_client);
+
+	/* Register sysfs hooks */
+	device_create_file(&new_client->dev, &dev_attr_out0_enable);
+	device_create_file(&new_client->dev, &dev_attr_out0_output);
+	device_create_file(&new_client->dev, &dev_attr_in0_input);
+	device_create_file(&new_client->dev, &dev_attr_in1_input);
+
+	/* Register input2 if not in "two differential inputs" mode */
+	if (input_mode != 3 )
+		device_create_file(&new_client->dev, &dev_attr_in2_input);
+		
+	/* Register input3 only in "four single ended inputs" mode */
+	if (input_mode == 0)
+		device_create_file(&new_client->dev, &dev_attr_in3_input);
+	
+	return 0;
+	
+	/* OK, this is not exactly good programming practice, usually. But it is
+	   very code-efficient in this case. */
+
+      exit_kfree:
+	kfree(new_client);
+      exit:
+	return err;
+}
+
+static int pcf8591_detach_client(struct i2c_client *client)
+{
+	int err;
+
+	if ((err = i2c_detach_client(client))) {
+		dev_err(&client->dev,
+			"Client deregistration failed, client not detached.\n");
+		return err;
+	}
+
+	kfree(client);
+	return 0;
+}
+
+/* Called when we have found a new PCF8591. */
+static void pcf8591_init_client(struct i2c_client *client)
+{
+	struct pcf8591_data *data = i2c_get_clientdata(client);
+	data->control = PCF8591_INIT_CONTROL;
+	data->aout = PCF8591_INIT_AOUT;
+
+	i2c_smbus_write_byte_data(client, data->control, data->aout);
+	
+	/* The first byte transmitted contains the conversion code of the 
+	   previous read cycle. FLUSH IT! */
+	i2c_smbus_read_byte(client);
+}
+
+static int pcf8591_read_channel(struct device *dev, int channel)
+{
+	u8 value;
+	struct i2c_client *client = to_i2c_client(dev);
+	struct pcf8591_data *data = i2c_get_clientdata(client);
+
+	down(&data->update_lock);
+
+	if ((data->control & PCF8591_CONTROL_AICH_MASK) != channel)
+	{
+		data->control = (data->control & ~PCF8591_CONTROL_AICH_MASK)
+			      | channel;
+		i2c_smbus_write_byte(client, data->control);
+	
+		/* The first byte transmitted contains the conversion code of 
+		   the previous read cycle. FLUSH IT! */
+		i2c_smbus_read_byte(client);
+	}
+	value = i2c_smbus_read_byte(client);
+
+	up(&data->update_lock);
+
+	if ((channel == 2 && input_mode == 2) ||
+	    (channel != 3 && (input_mode == 1 || input_mode == 3)))
+		return (10 * REG_TO_SIGNED(value));
+	else
+		return (10 * value);
+}
+
+static int __init pcf8591_init(void)
+{
+	if (input_mode < 0 || input_mode > 3) {
+		printk(KERN_WARNING "pcf8591: invalid input_mode (%d)\n",
+		       input_mode);
+		input_mode = 0;
+	}
+	return i2c_add_driver(&pcf8591_driver);
+}
+
+static void __exit pcf8591_exit(void)
+{
+	i2c_del_driver(&pcf8591_driver);
+}
+
+MODULE_AUTHOR("Aurelien Jarno <aurelien@aurel32.net>");
+MODULE_DESCRIPTION("PCF8591 driver");
+MODULE_LICENSE("GPL");
+
+module_init(pcf8591_init);
+module_exit(pcf8591_exit);


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                         ` Greg KH
@ 2004-04-14 22:24                                           ` Greg KH
  2004-04-14 22:24                                             ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.22, 2004/04/09 12:06:16-07:00, greg@kroah.com

[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(-)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Wed Apr 14 15:13:05 2004
+++ b/drivers/i2c/busses/Kconfig	Wed Apr 14 15:13:05 2004
@@ -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"
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Wed Apr 14 15:13:05 2004
+++ b/drivers/i2c/busses/Makefile	Wed Apr 14 15:13:05 2004
@@ -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


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                             ` Greg KH
@ 2004-04-14 22:24                                               ` Greg KH
  2004-04-14 22:24                                                 ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.24, 2004/04/12 15:15:36-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	Wed Apr 14 15:12:51 2004
+++ b/drivers/i2c/chips/it87.c	Wed Apr 14 15:12:51 2004
@@ -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:
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	Wed Apr 14 15:12:51 2004
+++ b/drivers/i2c/chips/via686a.c	Wed Apr 14 15:12:51 2004
@@ -748,9 +748,9 @@
 	return 0;
 
       ERROR3:
-	release_region(address, VIA686A_EXTENT);
 	kfree(data);
       ERROR0:
+	release_region(address, VIA686A_EXTENT);
 	return err;
 }
 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                           ` Greg KH
@ 2004-04-14 22:24                                             ` Greg KH
  2004-04-14 22:24                                               ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.23, 2004/04/12 15:15:13-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/adm1021.c b/drivers/i2c/chips/adm1021.c
--- a/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/adm1021.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/asb100.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/ds1621.c b/drivers/i2c/chips/ds1621.c
--- a/drivers/i2c/chips/ds1621.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/ds1621.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/eeprom.c b/drivers/i2c/chips/eeprom.c
--- a/drivers/i2c/chips/eeprom.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/eeprom.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
--- a/drivers/i2c/chips/fscher.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/fscher.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/gl518sm.c b/drivers/i2c/chips/gl518sm.c
--- a/drivers/i2c/chips/gl518sm.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/gl518sm.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/it87.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/lm75.c b/drivers/i2c/chips/lm75.c
--- a/drivers/i2c/chips/lm75.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/lm75.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/lm78.c b/drivers/i2c/chips/lm78.c
--- a/drivers/i2c/chips/lm78.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/lm78.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
--- a/drivers/i2c/chips/lm80.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/lm80.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/lm83.c b/drivers/i2c/chips/lm83.c
--- a/drivers/i2c/chips/lm83.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/lm83.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/lm85.c b/drivers/i2c/chips/lm85.c
--- a/drivers/i2c/chips/lm85.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/lm85.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/lm90.c b/drivers/i2c/chips/lm90.c
--- a/drivers/i2c/chips/lm90.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/lm90.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/pcf8574.c b/drivers/i2c/chips/pcf8574.c
--- a/drivers/i2c/chips/pcf8574.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/pcf8574.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
--- a/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 
diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/via686a.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/w83627hf.c b/drivers/i2c/chips/w83627hf.c
--- a/drivers/i2c/chips/w83627hf.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/w83627hf.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/w83l785ts.c b/drivers/i2c/chips/w83l785ts.c
--- a/drivers/i2c/chips/w83l785ts.c	Wed Apr 14 15:12:58 2004
+++ b/drivers/i2c/chips/w83l785ts.c	Wed Apr 14 15:12:58 2004
@@ -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;
 }
 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                       ` Greg KH
@ 2004-04-14 22:24                                         ` Greg KH
  2004-04-14 22:24                                           ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.21, 2004/04/09 12:06:02-07:00, greg@kroah.com

[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(-)


diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
--- a/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:13:11 2004
+++ b/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:13:11 2004
@@ -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);


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                                   ` Greg KH
@ 2004-04-14 22:24                                                     ` Greg KH
  2004-04-14 22:24                                                       ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.27, 2004/04/12 15:17:01-07:00, mhoffman@lightlink.com

[PATCH] I2C: fix asb100 bug

Hi nymisi, Greg:

* Nyeste Mihály <nymisi@freemail.hu> [2004-01-27 16:02:04 +0100]:
> 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(-)


diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	Wed Apr 14 15:12:31 2004
+++ b/drivers/i2c/chips/asb100.c	Wed Apr 14 15:12:31 2004
@@ -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; \
 }


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                               ` Greg KH
@ 2004-04-14 22:24                                                 ` Greg KH
  2004-04-14 22:24                                                   ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.25, 2004/04/12 15:16:08-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/w83781d.c b/drivers/i2c/chips/w83781d.c
--- a/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:12:45 2004
+++ b/drivers/i2c/chips/w83781d.c	Wed Apr 14 15:12:45 2004
@@ -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));


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                                     ` Greg KH
@ 2004-04-14 22:24                                                       ` Greg KH
  2004-04-14 22:24                                                         ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.28, 2004/04/12 15:17:24-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/lm80.c b/drivers/i2c/chips/lm80.c
--- a/drivers/i2c/chips/lm80.c	Wed Apr 14 15:12:26 2004
+++ b/drivers/i2c/chips/lm80.c	Wed Apr 14 15:12:26 2004
@@ -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)


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                                       ` Greg KH
@ 2004-04-14 22:24                                                         ` Greg KH
  2004-04-14 22:24                                                           ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.29, 2004/04/12 15:17:46-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/via686a.c b/drivers/i2c/chips/via686a.c
--- a/drivers/i2c/chips/via686a.c	Wed Apr 14 15:12:20 2004
+++ b/drivers/i2c/chips/via686a.c	Wed Apr 14 15:12:20 2004
@@ -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));


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                                 ` Greg KH
@ 2004-04-14 22:24                                                   ` Greg KH
  2004-04-14 22:24                                                     ` Greg KH
  0 siblings, 1 reply; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.26, 2004/04/12 15:16:36-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/fscher.c b/drivers/i2c/chips/fscher.c
--- a/drivers/i2c/chips/fscher.c	Wed Apr 14 15:12:39 2004
+++ b/drivers/i2c/chips/fscher.c	Wed Apr 14 15:12:39 2004
@@ -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 */
diff -Nru a/drivers/i2c/chips/it87.c b/drivers/i2c/chips/it87.c
--- a/drivers/i2c/chips/it87.c	Wed Apr 14 15:12:39 2004
+++ b/drivers/i2c/chips/it87.c	Wed Apr 14 15:12:39 2004
@@ -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;
 }
diff -Nru a/drivers/i2c/chips/pcf8591.c b/drivers/i2c/chips/pcf8591.c
--- a/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:12:39 2004
+++ b/drivers/i2c/chips/pcf8591.c	Wed Apr 14 15:12:39 2004
@@ -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, 


^ permalink raw reply	[flat|nested] 31+ messages in thread

* Re: [PATCH] I2C update for 2.6.5
  2004-04-14 22:24                                                         ` Greg KH
@ 2004-04-14 22:24                                                           ` Greg KH
  0 siblings, 0 replies; 31+ messages in thread
From: Greg KH @ 2004-04-14 22:24 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1643.36.30, 2004/04/14 13:10:38-07:00, khali@linux-fr.org

[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(-)


diff -Nru a/drivers/i2c/chips/asb100.c b/drivers/i2c/chips/asb100.c
--- a/drivers/i2c/chips/asb100.c	Wed Apr 14 15:12:13 2004
+++ b/drivers/i2c/chips/asb100.c	Wed Apr 14 15:12:13 2004
@@ -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)


^ permalink raw reply	[flat|nested] 31+ messages in thread

end of thread, other threads:[~2004-04-14 23:40 UTC | newest]

Thread overview: 31+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2004-04-14 22:22 [BK PATCH] I2C update for 2.6.5 Greg KH
2004-04-14 22:24 ` [PATCH] " Greg KH
2004-04-14 22:24   ` Greg KH
2004-04-14 22:24     ` Greg KH
2004-04-14 22:24       ` Greg KH
2004-04-14 22:24         ` Greg KH
2004-04-14 22:24           ` Greg KH
2004-04-14 22:24             ` Greg KH
2004-04-14 22:24               ` Greg KH
2004-04-14 22:24                 ` Greg KH
2004-04-14 22:24                   ` Greg KH
2004-04-14 22:24                     ` Greg KH
2004-04-14 22:24                       ` Greg KH
2004-04-14 22:24                         ` Greg KH
2004-04-14 22:24                           ` Greg KH
2004-04-14 22:24                             ` Greg KH
2004-04-14 22:24                               ` Greg KH
2004-04-14 22:24                                 ` Greg KH
2004-04-14 22:24                                   ` Greg KH
2004-04-14 22:24                                     ` Greg KH
2004-04-14 22:24                                       ` Greg KH
2004-04-14 22:24                                         ` Greg KH
2004-04-14 22:24                                           ` Greg KH
2004-04-14 22:24                                             ` Greg KH
2004-04-14 22:24                                               ` Greg KH
2004-04-14 22:24                                                 ` Greg KH
2004-04-14 22:24                                                   ` Greg KH
2004-04-14 22:24                                                     ` Greg KH
2004-04-14 22:24                                                       ` Greg KH
2004-04-14 22:24                                                         ` Greg KH
2004-04-14 22:24                                                           ` Greg KH

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox