All of lore.kernel.org
 help / color / mirror / Atom feed
* [BK PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23 ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:50 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, sensors

Hi,

Here's a set of i2c driver changes that start the conversion of the i2c
core and drivers over to the kernel driver model.  Eventually this will
allow all of the sysctl and proc mess to be removed for this subsystem.

These patches add i2c driver bus and i2c adapter driver support to the
driver core.  They also export a needed symbol from the driver core
(which Pat Mochel agreed with doing.) The patches also add three i2c
controllers that have been in the i2c cvs tree for a long time, and are
on a lot of people's machines.

The i2c core needs Christoph's previous patches to work properly, and
with that patch, and these patches, it all works properly on my machines
(tested on 4 different types of i2c controllers.)

Oh, and the i2c development team has given the ok for me to send these
patches to you, and for me to do this work.

Please pull from:  bk://kernel.bkbits.net/gregkh/linux/i2c-2.5


Things left to do after this:
	- clean up #ifdef mess in i2c controllers
	- fix the printk() calls to use proper levels
	- add i2c controller driver core support (present in the patch I
	  previously sent to lkml).
	- add i2c device core support.

thanks,

greg k-h

 arch/i386/kernel/dmi_scan.c      |    3 
 drivers/base/platform.c          |    3 
 drivers/i2c/busses/Kconfig       |   62 +++
 drivers/i2c/busses/Makefile      |    3 
 drivers/i2c/busses/i2c-ali15x3.c |  625 +++++++++++++++++++++++++++++-
 drivers/i2c/busses/i2c-amd756.c  |    3 
 drivers/i2c/busses/i2c-amd8111.c |    5 
 drivers/i2c/busses/i2c-i801.c    |  789 +++++++++++++++++++++++++++++++++++++--
 drivers/i2c/busses/i2c-piix4.c   |  651 ++++++++++++++++++++++++++++----
 drivers/i2c/i2c-core.c           |   46 ++
 include/linux/device.h           |    1 
 include/linux/i2c.h              |    5 
 12 files changed, 2063 insertions(+), 133 deletions(-)
-----

ChangeSet@1.1114, 2003-03-13 16:39:40-08:00, greg@kroah.com
  i2c: add driver model support to i2c adapter drivers

 drivers/i2c/busses/i2c-ali15x3.c |    6 ++++--
 drivers/i2c/busses/i2c-amd756.c  |    3 +++
 drivers/i2c/busses/i2c-amd8111.c |    5 ++++-
 drivers/i2c/busses/i2c-i801.c    |    5 ++++-
 drivers/i2c/busses/i2c-piix4.c   |    3 +++
 drivers/i2c/i2c-core.c           |   13 +++++++++++++
 include/linux/i2c.h              |    2 ++
 7 files changed, 33 insertions(+), 4 deletions(-)
------

ChangeSet@1.1113, 2003-03-13 16:37:27-08:00, greg@kroah.com
  driver core: Export the legacy_bus structure for drivers to use.

 drivers/base/platform.c |    3 ++-
 include/linux/device.h  |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)
------

ChangeSet@1.1112, 2003-03-13 12:26:39-08:00, greg@kroah.com
  i2c: add i2c sysfs bus support.

 drivers/i2c/i2c-core.c |   33 ++++++++++++++++++++++++++++++---
 include/linux/i2c.h    |    3 +++
 2 files changed, 33 insertions(+), 3 deletions(-)
------

ChangeSet@1.1111, 2003-03-13 12:16:52-08:00, greg@kroah.com
  i2c: i2c-piix4.c: Clean up the ibm dma scan logic
  
  Also export the is_unsafe_smbus variable, which is needed.

 arch/i386/kernel/dmi_scan.c    |    3 +++
 drivers/i2c/busses/i2c-piix4.c |   20 ++------------------
 2 files changed, 5 insertions(+), 18 deletions(-)
------

ChangeSet@1.1110, 2003-03-13 11:59:13-08:00, greg@kroah.com
  i2c: get i2c-piix4 driver to actually bind to a PCI device.

 drivers/i2c/busses/i2c-piix4.c |   99 +++++++++++++++++++++--------------------
 1 files changed, 52 insertions(+), 47 deletions(-)
------

ChangeSet@1.1109, 2003-03-13 11:52:26-08:00, greg@kroah.com
  i2c: add bus driver for Intel PIIX4 devices
  
  This is from the i2c CVS tree.

 drivers/i2c/busses/Kconfig     |   25 +
 drivers/i2c/busses/Makefile    |    1 
 drivers/i2c/busses/i2c-piix4.c |  529 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 554 insertions(+), 1 deletion(-)
------

ChangeSet@1.1108, 2003-03-13 11:38:03-08:00, greg@kroah.com
  i2c: get i2c-i801 driver to actually bind to a PCI device.

 drivers/i2c/busses/i2c-i801.c |   74 +++++++++++++++++++++---------------------
 1 files changed, 38 insertions(+), 36 deletions(-)
------

ChangeSet@1.1107, 2003-03-13 11:15:15-08:00, greg@kroah.com
  i2c: add bus driver for Intel 801 devices
  
  This is from the i2c CVS tree.

 drivers/i2c/busses/Kconfig    |   23 +
 drivers/i2c/busses/Makefile   |    1 
 drivers/i2c/busses/i2c-i801.c |  710 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 734 insertions(+)
------

ChangeSet@1.1106, 2003-03-13 10:50:41-08:00, greg@kroah.com
  i2c: get i2c-ali15x3 driver to actually bind to a PCI device.

 drivers/i2c/busses/i2c-ali15x3.c |   32 +++++++++-----------------------
 1 files changed, 9 insertions(+), 23 deletions(-)
------

ChangeSet@1.1105, 2003-03-13 10:31:07-08:00, greg@kroah.com
  i2c: add bus driver for ALI15x3 devices
  
  This is from the i2c CVS tree.

 drivers/i2c/busses/Kconfig       |   14 
 drivers/i2c/busses/Makefile      |    1 
 drivers/i2c/busses/i2c-ali15x3.c |  587 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 602 insertions(+)
------


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23       ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1107, 2003/03/13 11:15:15-08:00, greg@kroah.com

i2c: add bus driver for Intel 801 devices

This is from the i2c CVS tree.


 drivers/i2c/busses/Kconfig    |   23 +
 drivers/i2c/busses/Makefile   |    1 
 drivers/i2c/busses/i2c-i801.c |  710 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 734 insertions(+)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:50 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:50 2003
@@ -53,5 +53,28 @@
 	  in the lm_sensors package, which you can download at 
 	  http://www.lm-sensors.nu
 
+config I2C_I801
+	tristate "  Intel 801"
+	depends on I2C && I2C_PROC
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  801 family of mainboard I2C interfaces.  Specifically, the following
+	  versions of the chipset is supported:
+	    82801AA
+	    82801AB
+	    82801BA
+	    82801CA/CAM
+	    82801DB
+
+	  This can also be built as a module which can be inserted and removed 
+	  while the kernel is running.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  The module will be called i2c-i801.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+
 endmenu
 
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:50 2003
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:50 2003
@@ -5,3 +5,4 @@
 obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
+obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:57:50 2003
@@ -0,0 +1,710 @@
+/*
+    i801.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
+    <mdsxyz123@yahoo.com>
+
+    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.
+*/
+
+/*
+    SUPPORTED DEVICES	PCI ID
+    82801AA		2413           
+    82801AB		2423           
+    82801BA		2443           
+    82801CA/CAM		2483           
+    82801DB		24C3   (HW PEC supported, 32 byte buffer not supported)
+
+    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
+    For SMBus support, they are similar to the PIIX4 and are part
+    of Intel's '810' and other chipsets.
+    See the doc/busses/i2c-i801 file for details.
+    I2C Block Read and Process Call are not supported.
+*/
+
+/* Note: we assume there can only be one I801, with one SMBus interface */
+
+/* #define DEBUG 1 */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
+
+MODULE_LICENSE("GPL");
+
+#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
+#define HAVE_PEC
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS
+#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS	0x2483
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS
+#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS	0x24C3
+#endif
+
+static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
+                          PCI_DEVICE_ID_INTEL_82801AB_3,
+                          PCI_DEVICE_ID_INTEL_82801BA_2,
+			  PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
+			  PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
+                          0 };
+
+/* I801 SMBus address offsets */
+#define SMBHSTSTS (0 + i801_smba)
+#define SMBHSTCNT (2 + i801_smba)
+#define SMBHSTCMD (3 + i801_smba)
+#define SMBHSTADD (4 + i801_smba)
+#define SMBHSTDAT0 (5 + i801_smba)
+#define SMBHSTDAT1 (6 + i801_smba)
+#define SMBBLKDAT (7 + i801_smba)
+#define SMBPEC    (8 + i801_smba)	/* ICH4 only */
+#define SMBAUXSTS (12 + i801_smba)	/* ICH4 only */
+#define SMBAUXCTL (13 + i801_smba)	/* ICH4 only */
+
+/* PCI Address Constants */
+#define SMBBA     0x020
+#define SMBHSTCFG 0x040
+#define SMBREV    0x008
+
+/* Host configuration bits for SMBHSTCFG */
+#define SMBHSTCFG_HST_EN      1
+#define SMBHSTCFG_SMB_SMI_EN  2
+#define SMBHSTCFG_I2C_EN      4
+
+/* Other settings */
+#define MAX_TIMEOUT 100
+#define ENABLE_INT9 0	/* set to 0x01 to enable - untested */
+
+/* I801 command constants */
+#define I801_QUICK          0x00
+#define I801_BYTE           0x04
+#define I801_BYTE_DATA      0x08
+#define I801_WORD_DATA      0x0C
+#define I801_PROC_CALL      0x10	/* later chips only, unimplemented */
+#define I801_BLOCK_DATA     0x14
+#define I801_I2C_BLOCK_DATA 0x18	/* unimplemented */
+#define I801_BLOCK_LAST     0x34
+#define I801_I2C_BLOCK_LAST 0x38	/* unimplemented */
+#define I801_START          0x40
+#define I801_PEC_EN         0x80	/* ICH4 only */
+
+/* insmod parameters */
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the I801 at the given address. VERY DANGEROUS! */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Forcibly enable the I801 at the given address. "
+		 "EXTREMELY DANGEROUS!");
+
+
+
+
+
+static void i801_do_pause(unsigned int amount);
+static int i801_transaction(void);
+static int i801_block_transaction(union i2c_smbus_data *data,
+				  char read_write, int command);
+
+
+
+
+static unsigned short i801_smba = 0;
+static struct pci_dev *I801_dev = NULL;
+static int isich4 = 0;
+
+/* Detect whether a I801 can be found, and initialize it, where necessary.
+   Note the differences between kernels with the old PCI BIOS interface and
+   newer kernels with the real PCI interface. In compat.h some things are
+   defined to make the transition easier. */
+int i801_setup(void)
+{
+	int error_return = 0;
+	int *num = supported;
+	unsigned char temp;
+
+	/* First check whether we can access PCI at all */
+	if (pci_present() == 0) {
+		printk(KERN_WARNING "i2c-i801.o: Error: No PCI-bus found!\n");
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	/* Look for each chip */
+	/* Note: we keep on searching until we have found 'function 3' */
+	I801_dev = NULL;
+	do {
+		if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+					      *num, I801_dev))) {
+			if(PCI_FUNC(I801_dev->devfn) != 3)
+				continue;
+			break;
+		}
+		num++;
+	} while (*num != 0);
+
+	if (I801_dev == NULL) {
+		printk
+		    (KERN_WARNING "i2c-i801.o: Error: Can't detect I801, function 3!\n");
+		error_return = -ENODEV;
+		goto END;
+	}
+	isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS;
+
+/* Determine the address of the SMBus areas */
+	if (force_addr) {
+		i801_smba = force_addr & 0xfff0;
+	} else {
+		pci_read_config_word(I801_dev, SMBBA, &i801_smba);
+		i801_smba &= 0xfff0;
+		if(i801_smba == 0) {
+			printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+			return -ENODEV;
+		}
+	}
+
+	if (check_region(i801_smba, (isich4 ? 16 : 8))) {
+		printk
+		    (KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n",
+		     i801_smba);
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
+	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
+	pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
+/* If force_addr is set, we program the new address here. Just to make
+   sure, we disable the device first. */
+	if (force_addr) {
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
+		pci_write_config_word(I801_dev, SMBBA, i801_smba);
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
+		printk
+		    (KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new "
+		     "address %04x!\n", i801_smba);
+	} else if ((temp & 1) == 0) {
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
+		printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n");
+	}
+
+	request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus");
+
+#ifdef DEBUG
+	if (temp & 0x02)
+		printk
+		    (KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
+	else
+		printk
+		    (KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
+
+	pci_read_config_byte(I801_dev, SMBREV, &temp);
+	printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp);
+	printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba);
+#endif				/* DEBUG */
+
+      END:
+	return error_return;
+}
+
+
+void i801_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+int i801_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
+	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
+		       temp);
+#endif
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp);
+#endif
+			return -1;
+		} else {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Successfull!\n");
+#endif
+		}
+	}
+
+	outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+
+	/* We will always wait for a fraction of a second! */
+	do {
+		i801_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
+		result = -1;
+#endif
+	}
+
+	if (temp & 0x10) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+	if (temp & 0x08) {
+		result = -1;
+		printk
+		    (KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n"
+		     "reset. (sorry!)\n");
+		/* Clock stops and slave is stuck in mid-transmission */
+	}
+
+	if (temp & 0x04) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
+#endif
+	}
+
+	if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n",
+		     temp);
+#endif
+	}
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* All-inclusive block transaction function */
+int i801_block_transaction(union i2c_smbus_data *data, char read_write, 
+                           int command)
+{
+	int i, len;
+	int smbcmd;
+	int temp;
+	int result = 0;
+	int timeout;
+        unsigned char hostc, errmask;
+
+        if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+                if (read_write == I2C_SMBUS_WRITE) {
+                        /* set I2C_EN bit in configuration register */
+                        pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+                        pci_write_config_byte(I801_dev, SMBHSTCFG, 
+                                              hostc | SMBHSTCFG_I2C_EN);
+                } else {
+                        printk("i2c-i801.o: "
+                               "I2C_SMBUS_I2C_BLOCK_READ not supported!\n");
+                        return -1;
+                }
+        }
+
+	if (read_write == I2C_SMBUS_WRITE) {
+		len = data->block[0];
+		if (len < 1)
+			len = 1;
+		if (len > 32)
+			len = 32;
+		outb_p(len, SMBHSTDAT0);
+		outb_p(data->block[1], SMBBLKDAT);
+	} else {
+		len = 32;	/* max for reads */
+	}
+
+	if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+		/* set 32 byte buffer */
+	}
+
+	for (i = 1; i <= len; i++) {
+		if (i == len && read_write == I2C_SMBUS_READ)
+			smbcmd = I801_BLOCK_LAST;
+		else
+			smbcmd = I801_BLOCK_DATA;
+#if 0 /* now using HW PEC */
+		if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC)
+			smbcmd |= I801_PEC_EN;
+#endif
+		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
+
+#ifdef DEBUG
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, "
+		     "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT),
+		     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		     inb_p(SMBBLKDAT));
+#endif
+
+		/* Make sure the SMBus host is ready to start transmitting */
+		temp = inb_p(SMBHSTSTS);
+                if (i == 1) {
+                    /* Erronenous conditions before transaction: 
+                     * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
+                    errmask=0x9f; 
+                } else {
+                    /* Erronenous conditions during transaction: 
+                     * Failed, Bus_Err, Dev_Err, Intr */
+                    errmask=0x1e; 
+                }
+		if (temp & errmask) {
+#ifdef DEBUG
+			printk
+			    (KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
+			     temp);
+#endif
+			outb_p(temp, SMBHSTSTS);
+			if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
+				printk
+				    (KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n",
+				     temp);
+				result = -1;
+                                goto END;
+			}
+			if (i != 1) {
+                                result = -1;  /* if die in middle of block transaction, fail */
+                                goto END;
+                        }
+		}
+
+		if (i == 1) {
+#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */
+			if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+				if(read_write == I2C_SMBUS_WRITE)
+					outb_p(data->block[len + 1], SMBPEC);
+			}
+#endif
+			outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+		}
+
+		/* We will always wait for a fraction of a second! */
+		timeout = 0;
+		do {
+			temp = inb_p(SMBHSTSTS);
+			i801_do_pause(1);
+		}
+		    while ((!(temp & 0x80))
+			   && (timeout++ < MAX_TIMEOUT));
+
+		/* If the SMBus is still busy, we give up */
+		if (timeout >= MAX_TIMEOUT) {
+			result = -1;
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
+#endif
+		}
+
+		if (temp & 0x10) {
+			result = -1;
+#ifdef DEBUG
+			printk
+			    (KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
+#endif
+		} else if (temp & 0x08) {
+			result = -1;
+			printk(KERN_ERR "i2c-i801.o: Bus collision!\n");
+		} else if (temp & 0x04) {
+			result = -1;
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
+#endif
+		}
+
+		if (i == 1 && read_write == I2C_SMBUS_READ) {
+			len = inb_p(SMBHSTDAT0);
+			if (len < 1)
+				len = 1;
+			if (len > 32)
+				len = 32;
+			data->block[0] = len;
+		}
+
+                /* Retrieve/store value in SMBBLKDAT */
+		if (read_write == I2C_SMBUS_READ)
+			data->block[i] = inb_p(SMBBLKDAT);
+		if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
+			outb_p(data->block[i+1], SMBBLKDAT);
+		if ((temp & 0x9e) != 0x00)
+			outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */
+
+#ifdef DEBUG
+		if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
+			printk
+			    (KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n",
+			     temp);
+		}
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, "
+		     "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT),
+		     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		     inb_p(SMBBLKDAT));
+#endif
+
+		if (result < 0)
+			goto END;
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && command == I2C_SMBUS_BLOCK_DATA_PEC) {
+		/* wait for INTR bit as advised by Intel */
+		timeout = 0;
+		do {
+			temp = inb_p(SMBHSTSTS);
+			i801_do_pause(1);
+		} while ((!(temp & 0x02))
+			   && (timeout++ < MAX_TIMEOUT));
+
+		if (timeout >= MAX_TIMEOUT) {
+			printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n");
+		}
+#if 0 /* now using HW PEC */
+		if(read_write == I2C_SMBUS_READ) {
+			data->block[len + 1] = inb_p(SMBPEC);
+		}
+#endif
+		outb_p(temp, SMBHSTSTS); 
+	}
+#endif
+        result = 0;
+END:
+        if (command == I2C_SMBUS_I2C_BLOCK_DATA) {
+                /* restore saved configuration register value */
+		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
+        }
+	return result;
+}
+
+/* Return -1 on error. */
+s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+		char read_write, u8 command, int size,
+		union i2c_smbus_data * data)
+{
+	int hwpec = 0;
+	int block = 0;
+	int ret, xact = 0;
+
+#ifdef HAVE_PEC
+	if(isich4)
+		hwpec = (flags & I2C_CLIENT_PEC) != 0;
+#endif
+
+	switch (size) {
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		xact = I801_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		xact = I801_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		xact = I801_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		xact = I801_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+#ifdef HAVE_PEC
+	case I2C_SMBUS_BLOCK_DATA_PEC:
+		if(hwpec && size == I2C_SMBUS_BLOCK_DATA)
+			size = I2C_SMBUS_BLOCK_DATA_PEC;
+#endif
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		block = 1;
+		break;
+	case I2C_SMBUS_PROC_CALL:
+	default:
+		printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size);
+		return -1;
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && hwpec) {
+		if(size != I2C_SMBUS_QUICK &&
+		   size != I2C_SMBUS_I2C_BLOCK_DATA)
+			outb_p(1, SMBAUXCTL);	/* enable HW PEC */
+	}
+#endif
+	if(block)
+		ret = i801_block_transaction(data, read_write, size);
+	else {
+		outb_p(xact | ENABLE_INT9, SMBHSTCNT);
+		ret = i801_transaction();
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && hwpec) {
+		if(size != I2C_SMBUS_QUICK &&
+		   size != I2C_SMBUS_I2C_BLOCK_DATA)
+			outb_p(0, SMBAUXCTL);
+	}
+#endif
+
+	if(block)
+		return ret;
+	if(ret)
+		return -1;
+	if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
+		return 0;
+
+	switch (xact & 0x7f) {
+	case I801_BYTE:	/* Result put in SMBHSTDAT0 */
+	case I801_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case I801_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	}
+	return 0;
+}
+
+
+u32 i801_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
+#ifdef HAVE_PEC
+	     | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
+	                 I2C_FUNC_SMBUS_HWPEC_CALC
+	               : 0)
+#endif
+	    ;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= i801_access,
+	.functionality	= i801_func,
+};
+
+static struct i2c_adapter i801_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id i801_ids[] __devinitdata = {
+	{ 0, }
+};
+
+static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+
+	if (i801_setup()) {
+		printk
+		    (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n");
+		return -ENODEV;
+	}
+
+	sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
+		i801_smba);
+	i2c_add_adapter(&i801_adapter);
+}
+
+static void __devexit i801_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&i801_adapter);
+}
+
+static struct pci_driver i801_driver = {
+	.name		= "i801 smbus",
+	.id_table	= i801_ids,
+	.probe		= i801_probe,
+	.remove		= __devexit_p(i801_remove),
+};
+
+static int __init i2c_i801_init(void)
+{
+	printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&i801_driver);
+}
+
+
+static void __exit i2c_i801_exit(void)
+{
+	pci_unregister_driver(&i801_driver);
+	release_region(i801_smba, (isich4 ? 16 : 8));
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("I801 SMBus driver");
+
+module_init(i2c_i801_init);
+module_exit(i2c_i801_exit);


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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23   ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1105, 2003/03/13 10:31:07-08:00, greg@kroah.com

i2c: add bus driver for ALI15x3 devices

This is from the i2c CVS tree.


 drivers/i2c/busses/Kconfig       |   14 
 drivers/i2c/busses/Makefile      |    1 
 drivers/i2c/busses/i2c-ali15x3.c |  587 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 602 insertions(+)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Thu Mar 13 16:58:06 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 16:58:06 2003
@@ -5,6 +5,20 @@
 
 menu "I2C Hardware Sensors Mainboard support"
 
+config I2C_ALI15X3
+	tristate "  ALI 15x3"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the
+	  Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
+
+	  This can also be built as a module.  If so, the module will be
+	  called i2c-ali15x3.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at
+	  http://www.lm-sensors.nu
+
 config I2C_AMD756
 	tristate "  AMD 756/766"
 	depends on I2C && I2C_PROC
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Thu Mar 13 16:58:06 2003
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 16:58:06 2003
@@ -2,5 +2,6 @@
 # Makefile for the kernel hardware sensors bus drivers.
 #
 
+obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:58:06 2003
@@ -0,0 +1,587 @@
+/*
+    ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1999  Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com> and
+    Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+    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.
+*/
+
+/*
+    This is the driver for the SMB Host controller on
+    Acer Labs Inc. (ALI) M1541 and M1543C South Bridges.
+
+    The M1543C is a South bridge for desktop systems.
+    The M1533 is a South bridge for portable systems.
+    They are part of the following ALI chipsets:
+       "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge
+       with AGP and 100MHz CPU Front Side bus
+       "Aladdin V": Includes the M1541 Socket 7 North bridge
+       with AGP and 100MHz CPU Front Side bus
+       "Aladdin IV": Includes the M1541 Socket 7 North bridge
+       with host bus up to 83.3 MHz.
+    For an overview of these chips see http://www.acerlabs.com
+
+    The M1533/M1543C devices appear as FOUR separate devices
+    on the PCI bus. An output of lspci will show something similar
+    to the following:
+
+	00:02.0 USB Controller: Acer Laboratories Inc. M5237
+	00:03.0 Bridge: Acer Laboratories Inc. M7101
+	00:07.0 ISA bridge: Acer Laboratories Inc. M1533
+	00:0f.0 IDE interface: Acer Laboratories Inc. M5229
+
+    The SMB controller is part of the 7101 device, which is an
+    ACPI-compliant Power Management Unit (PMU).
+
+    The whole 7101 device has to be enabled for the SMB to work.
+    You can't just enable the SMB alone.
+    The SMB and the ACPI have separate I/O spaces.
+    We make sure that the SMB is enabled. We leave the ACPI alone.
+
+    This driver controls the SMB Host only.
+    The SMB Slave controller on the M15X3 is not enabled.
+
+    This driver does not use interrupts.
+*/
+
+/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+/* ALI15X3 SMBus address offsets */
+#define SMBHSTSTS (0 + ali15x3_smba)
+#define SMBHSTCNT (1 + ali15x3_smba)
+#define SMBHSTSTART (2 + ali15x3_smba)
+#define SMBHSTCMD (7 + ali15x3_smba)
+#define SMBHSTADD (3 + ali15x3_smba)
+#define SMBHSTDAT0 (4 + ali15x3_smba)
+#define SMBHSTDAT1 (5 + ali15x3_smba)
+#define SMBBLKDAT (6 + ali15x3_smba)
+
+/* PCI Address Constants */
+#define SMBCOM    0x004
+#define SMBBA     0x014
+#define SMBATPC   0x05B		/* used to unlock xxxBA registers */
+#define SMBHSTCFG 0x0E0
+#define SMBSLVC   0x0E1
+#define SMBCLK    0x0E2
+#define SMBREV    0x008
+
+/* Other settings */
+#define MAX_TIMEOUT 200		/* times 1/100 sec */
+#define ALI15X3_SMB_IOSIZE 32
+
+/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB.
+   We don't use these here. If the bases aren't set to some value we
+   tell user to upgrade BIOS and we fail.
+*/
+#define ALI15X3_SMB_DEFAULTBASE 0xE800
+
+/* ALI15X3 address lock bits */
+#define ALI15X3_LOCK	0x06
+
+/* ALI15X3 command constants */
+#define ALI15X3_ABORT      0x02
+#define ALI15X3_T_OUT      0x04
+#define ALI15X3_QUICK      0x00
+#define ALI15X3_BYTE       0x10
+#define ALI15X3_BYTE_DATA  0x20
+#define ALI15X3_WORD_DATA  0x30
+#define ALI15X3_BLOCK_DATA 0x40
+#define ALI15X3_BLOCK_CLR  0x80
+
+/* ALI15X3 status register bits */
+#define ALI15X3_STS_IDLE	0x04
+#define ALI15X3_STS_BUSY	0x08
+#define ALI15X3_STS_DONE	0x10
+#define ALI15X3_STS_DEV		0x20	/* device error */
+#define ALI15X3_STS_COLL	0x40	/* collision or no response */
+#define ALI15X3_STS_TERM	0x80	/* terminated by abort */
+#define ALI15X3_STS_ERR		0xE0	/* all the bad error bits */
+
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the device at the given address. */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Initialize the base address of the i2c controller");
+
+
+static void ali15x3_do_pause(unsigned int amount);
+static int ali15x3_transaction(void);
+
+static unsigned short ali15x3_smba = 0;
+
+/* Detect whether a ALI15X3 can be found, and initialize it, where necessary.
+   Note the differences between kernels with the old PCI BIOS interface and
+   newer kernels with the real PCI interface. In compat.h some things are
+   defined to make the transition easier. */
+int ali15x3_setup(void)
+{
+	u16 a;
+	unsigned char temp;
+
+	struct pci_dev *ALI15X3_dev;
+
+	/* First check whether we can access PCI at all */
+	if (pci_present() == 0) {
+		printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
+		return -ENODEV;
+	}
+
+	/* Look for the ALI15X3, M7101 device */
+	ALI15X3_dev = NULL;
+	ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
+				      PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
+	if (ALI15X3_dev == NULL) {
+		printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
+		return -ENODEV;
+	}
+
+/* Check the following things:
+	- SMB I/O address is initialized
+	- Device is enabled
+	- We can use the addresses
+*/
+
+/* Unlock the register.
+   The data sheet says that the address registers are read-only
+   if the lock bits are 1, but in fact the address registers
+   are zero unless you clear the lock bits.
+*/
+	pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
+	if (temp & ALI15X3_LOCK) {
+		temp &= ~ALI15X3_LOCK;
+		pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
+	}
+
+/* Determine the address of the SMBus area */
+	pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
+	ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
+	if (ali15x3_smba == 0 && force_addr == 0) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+		return -ENODEV;
+	}
+
+	if(force_addr)
+		ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
+
+	if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n",
+		     ali15x3_smba);
+		return -ENODEV;
+	}
+
+	if(force_addr) {
+		printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba);
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))
+			return -ENODEV;
+		if (PCIBIOS_SUCCESSFUL !=
+		    pci_read_config_word(ALI15X3_dev, SMBBA, &a))
+			return -ENODEV;
+		if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
+			/* make sure it works */
+			printk("i2c-ali15x3.o: force address failed - not supported?\n");
+			return -ENODEV;
+		}
+	}
+/* check if whole device is enabled */
+	pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
+	if ((temp & 1) == 0) {
+		printk("i2c-ali15x3: enabling SMBus device\n");
+		pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
+	}
+
+/* Is SMB Host controller enabled? */
+	pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
+	if ((temp & 1) == 0) {
+		printk("i2c-ali15x3: enabling SMBus controller\n");
+		pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
+	}
+
+/* set SMB clock to 74KHz as recommended in data sheet */
+	pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
+
+	/* Everything is happy, let's grab the memory and set things up. */
+	request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb");
+
+#ifdef DEBUG
+/*
+  The interrupt routing for SMB is set up in register 0x77 in the
+  1533 ISA Bridge device, NOT in the 7101 device.
+  Don't bother with finding the 1533 device and reading the register.
+  if ((....... & 0x0F) == 1)
+     printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n");
+*/
+	pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
+	printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp);
+	printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba);
+#endif				/* DEBUG */
+
+	return 0;
+}
+
+
+/* Internally used pause function */
+void ali15x3_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+/* Another internally used function */
+int ali15x3_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+	     inb_p(SMBHSTDAT1));
+#endif
+
+	/* get status */
+	temp = inb_p(SMBHSTSTS);
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	/* Check the busy bit first */
+	if (temp & ALI15X3_STS_BUSY) {
+/*
+   If the host controller is still busy, it may have timed out in the previous transaction,
+   resulting in a "SMBus Timeout" printk.
+   I've tried the following to reset a stuck busy bit.
+	1. Reset the controller with an ABORT command.
+	   (this doesn't seem to clear the controller if an external device is hung)
+	2. Reset the controller and the other SMBus devices with a T_OUT command.
+	   (this clears the host busy bit if an external device is hung,
+	   but it comes back upon a new access to a device)
+	3. Disable and reenable the controller in SMBHSTCFG
+   Worst case, nothing seems to work except power reset.
+*/
+/* Abort - reset the host controller */
+/*
+#ifdef DEBUG
+    printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp);
+#endif
+    outb_p(ALI15X3_ABORT, SMBHSTCNT);
+    temp = inb_p(SMBHSTSTS);
+    if (temp & ALI15X3_STS_BUSY) {
+*/
+
+/*
+   Try resetting entire SMB bus, including other devices -
+   This may not work either - it clears the BUSY bit but
+   then the BUSY bit may come back on when you try and use the chip again.
+   If that's the case you are stuck.
+*/
+		printk
+		    ("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
+		     temp);
+		outb_p(ALI15X3_T_OUT, SMBHSTCNT);
+		temp = inb_p(SMBHSTSTS);
+	}
+/*
+  }
+*/
+
+	/* now check the error bits and the busy bit */
+	if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
+		/* do a clear-on-write */
+		outb_p(0xFF, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) &
+		    (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
+			/* this is probably going to be correctable only by a power reset
+			   as one of the bits now appears to be stuck */
+			/* This may be a bus or device with electrical problems. */
+			printk
+			    ("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",
+			     temp);
+			return -1;
+		}
+	} else {
+		/* check and clear done bit */
+		if (temp & ALI15X3_STS_DONE) {
+			outb_p(temp, SMBHSTSTS);
+		}
+	}
+
+	/* start the transaction by writing anything to the start register */
+	outb_p(0xFF, SMBHSTSTART);
+
+	/* We will always wait for a fraction of a second! */
+	timeout = 0;
+	do {
+		ali15x3_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
+		 && (timeout++ < MAX_TIMEOUT));
+
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+		result = -1;
+		printk("i2c-ali15x3.o: SMBus Timeout!\n");
+	}
+
+	if (temp & ALI15X3_STS_TERM) {
+		result = -1;
+#ifdef DEBUG
+		printk("i2c-ali15x3.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+/*
+  Unfortunately the ALI SMB controller maps "no response" and "bus collision"
+  into a single bit. No reponse is the usual case so don't
+  do a printk.
+  This means that bus collisions go unreported.
+*/
+	if (temp & ALI15X3_STS_COLL) {
+		result = -1;
+#ifdef DEBUG
+		printk
+		    ("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n",
+		     inb_p(SMBHSTADD));
+#endif
+	}
+
+/* haven't ever seen this */
+	if (temp & ALI15X3_STS_DEV) {
+		result = -1;
+		printk("i2c-ali15x3.o: Error: device error\n");
+	}
+#ifdef DEBUG
+	printk
+	    ("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+	     inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* Return -1 on error. */
+s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
+		   unsigned short flags, char read_write, u8 command,
+		   int size, union i2c_smbus_data * data)
+{
+	int i, len;
+	int temp;
+	int timeout;
+
+/* clear all the bits (clear-on-write) */
+	outb_p(0xFF, SMBHSTSTS);
+/* make sure SMBus is idle */
+	temp = inb_p(SMBHSTSTS);
+	for (timeout = 0;
+	     (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
+	     timeout++) {
+		ali15x3_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT) {
+		printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n",
+		       temp);
+	}
+
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		printk
+		    ("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n");
+		return -1;
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		size = ALI15X3_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		size = ALI15X3_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		size = ALI15X3_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		size = ALI15X3_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len < 0) {
+				len = 0;
+				data->block[0] = len;
+			}
+			if (len > 32) {
+				len = 32;
+				data->block[0] = len;
+			}
+			outb_p(len, SMBHSTDAT0);
+			outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);	/* Reset SMBBLKDAT */
+			for (i = 1; i <= len; i++)
+				outb_p(data->block[i], SMBBLKDAT);
+		}
+		size = ALI15X3_BLOCK_DATA;
+		break;
+	}
+
+	outb_p(size, SMBHSTCNT);	/* output command */
+
+	if (ali15x3_transaction())	/* Error in transaction */
+		return -1;
+
+	if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
+		return 0;
+
+
+	switch (size) {
+	case ALI15X3_BYTE:	/* Result put in SMBHSTDAT0 */
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case ALI15X3_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case ALI15X3_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	case ALI15X3_BLOCK_DATA:
+		len = inb_p(SMBHSTDAT0);
+		if (len > 32)
+			len = 32;
+		data->block[0] = len;
+		outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);	/* Reset SMBBLKDAT */
+		for (i = 1; i <= data->block[0]; i++) {
+			data->block[i] = inb_p(SMBBLKDAT);
+#ifdef DEBUG
+			printk
+			    ("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n",
+			     len, i, data->block[i]);
+#endif	/* DEBUG */
+		}
+		break;
+	}
+	return 0;
+}
+
+
+u32 ali15x3_func(struct i2c_adapter *adapter)
+{
+	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 struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= ali15x3_access,
+	.functionality	= ali15x3_func,
+};
+
+static struct i2c_adapter ali15x3_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id ali15x3_ids[] __devinitdata = {
+	{ 0, }
+};
+
+static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	if (ali15x3_setup()) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
+
+		return -ENODEV;
+	}
+
+	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
+		ali15x3_smba);
+	i2c_add_adapter(&ali15x3_adapter);
+}
+
+static void __devexit ali15x3_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&ali15x3_adapter);
+}
+
+static struct pci_driver ali15x3_driver = {
+	.name		= "ali15x3 smbus",
+	.id_table	= ali15x3_ids,
+	.probe		= ali15x3_probe,
+	.remove		= __devexit_p(ali15x3_remove),
+};
+
+static int __init i2c_ali15x3_init(void)
+{
+	printk("i2c-ali15x3.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&ali15x3_driver);
+}
+
+
+static void __exit i2c_ali15x3_exit(void)
+{
+	pci_unregister_driver(&ali15x3_driver);
+	release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("ALI15X3 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_ali15x3_init);
+module_exit(i2c_ali15x3_exit);


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23       ` Greg KH
@ 2005-05-19  6:23         ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1108, 2003/03/13 11:38:03-08:00, greg@kroah.com

i2c: get i2c-i801 driver to actually bind to a PCI device.


 drivers/i2c/busses/i2c-i801.c |   74 +++++++++++++++++++++---------------------
 1 files changed, 38 insertions(+), 36 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:57:41 2003
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:57:41 2003
@@ -128,49 +128,21 @@
 static int i801_block_transaction(union i2c_smbus_data *data,
 				  char read_write, int command);
 
+static unsigned short i801_smba;
+static struct pci_dev *I801_dev;
+static int isich4;
 
-
-
-static unsigned short i801_smba = 0;
-static struct pci_dev *I801_dev = NULL;
-static int isich4 = 0;
-
-/* Detect whether a I801 can be found, and initialize it, where necessary.
-   Note the differences between kernels with the old PCI BIOS interface and
-   newer kernels with the real PCI interface. In compat.h some things are
-   defined to make the transition easier. */
-int i801_setup(void)
+static int i801_setup(struct pci_dev *dev)
 {
 	int error_return = 0;
 	int *num = supported;
 	unsigned char temp;
 
-	/* First check whether we can access PCI at all */
-	if (pci_present() == 0) {
-		printk(KERN_WARNING "i2c-i801.o: Error: No PCI-bus found!\n");
-		error_return = -ENODEV;
-		goto END;
-	}
-
-	/* Look for each chip */
 	/* Note: we keep on searching until we have found 'function 3' */
-	I801_dev = NULL;
-	do {
-		if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					      *num, I801_dev))) {
-			if(PCI_FUNC(I801_dev->devfn) != 3)
-				continue;
-			break;
-		}
-		num++;
-	} while (*num != 0);
+	if(PCI_FUNC(dev->devfn) != 3)
+		return -ENODEV;
 
-	if (I801_dev == NULL) {
-		printk
-		    (KERN_WARNING "i2c-i801.o: Error: Can't detect I801, function 3!\n");
-		error_return = -ENODEV;
-		goto END;
-	}
+	I801_dev = dev;
 	isich4 = *num == PCI_DEVICE_ID_INTEL_82801DB_SMBUS;
 
 /* Determine the address of the SMBus areas */
@@ -658,13 +630,43 @@
 
 
 static struct pci_device_id i801_ids[] __devinitdata = {
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801AA_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801AB_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801BA_2,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
 	{ 0, }
 };
 
 static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 
-	if (i801_setup()) {
+	if (i801_setup(dev)) {
 		printk
 		    (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n");
 		return -ENODEV;


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23                     ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1114, 2003/03/13 16:39:40-08:00, greg@kroah.com

i2c: add driver model support to i2c adapter drivers


 drivers/i2c/busses/i2c-ali15x3.c |    6 ++++--
 drivers/i2c/busses/i2c-amd756.c  |    3 +++
 drivers/i2c/busses/i2c-amd8111.c |    5 ++++-
 drivers/i2c/busses/i2c-i801.c    |    5 ++++-
 drivers/i2c/busses/i2c-piix4.c   |    3 +++
 drivers/i2c/i2c-core.c           |   13 +++++++++++++
 include/linux/i2c.h              |    2 ++
 7 files changed, 33 insertions(+), 4 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:56:52 2003
@@ -531,10 +531,12 @@
 		return -ENODEV;
 	}
 
+	/* set up the driverfs linkage to our parent device */
+	ali15x3_adapter.dev.parent = &dev->dev;
+
 	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
 		ali15x3_smba);
-	i2c_add_adapter(&ali15x3_adapter);
-	return 0;
+	return i2c_add_adapter(&ali15x3_adapter);
 }
 
 static void __devexit ali15x3_remove(struct pci_dev *dev)
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-amd756.c	Thu Mar 13 16:56:52 2003
@@ -375,6 +375,9 @@
 	printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport);
 #endif
 
+	/* set up the driverfs linkage to our parent device */
+	amd756_adapter.dev.parent = &pdev->dev;
+
 	sprintf(amd756_adapter.name,
 		"SMBus AMD75x adapter at %04x", amd756_ioport);
 
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
@@ -363,6 +363,9 @@
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 
+	/* set up the driverfs linkage to our parent device */
+	smbus->adapter.dev.parent = &dev->dev;
+
 	error = i2c_add_adapter(&smbus->adapter);
 	if (error)
 		goto out_release_region;
@@ -389,7 +392,7 @@
 }
 
 static struct pci_driver amd8111_driver = {
-	.name		= "amd8111 smbus 2.0",
+	.name		= "amd8111 smbus",
 	.id_table	= amd8111_ids,
 	.probe		= amd8111_probe,
 	.remove		= __devexit_p(amd8111_remove),
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:56:52 2003
@@ -672,9 +672,12 @@
 		return -ENODEV;
 	}
 
+	/* set up the driverfs linkage to our parent device */
+	i801_adapter.dev.parent = &dev->dev;
+
 	sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
 		i801_smba);
-	i2c_add_adapter(&i801_adapter);
+	return i2c_add_adapter(&i801_adapter);
 }
 
 static void __devexit i801_remove(struct pci_dev *dev)
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:56:52 2003
@@ -473,6 +473,9 @@
 	if (retval)
 		return retval;
 
+	/* set up the driverfs linkage to our parent device */
+	piix4_adapter.dev.parent = &dev->dev;
+
 	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
 		piix4_smba);
 
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/i2c-core.c	Thu Mar 13 16:56:52 2003
@@ -87,6 +87,16 @@
 	init_MUTEX(&adap->bus);
 	init_MUTEX(&adap->list);
 
+	/* Add the adapter to the driver core.
+	 * If the parent pointer is not set up,
+	 * we add this adapter to the legacy bus.
+	 */
+	if (adap->dev.parent == NULL)
+		adap->dev.parent = &legacy_bus;
+	sprintf(adap->dev.bus_id, "i2c-%d", i);
+	strcpy(adap->dev.name, "i2c controller");
+	device_register(&adap->dev);
+
 	/* inform drivers of new adapters */
 	for (j=0;j<I2C_DRIVER_MAX;j++)
 		if (drivers[j]!=NULL && 
@@ -153,6 +163,9 @@
 	}
 
 	i2cproc_remove(i);
+
+	/* clean up the sysfs representation */
+	device_unregister(&adap->dev);
 
 	adapters[i] = NULL;
 
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Thu Mar 13 16:56:52 2003
+++ b/include/linux/i2c.h	Thu Mar 13 16:56:52 2003
@@ -231,12 +231,14 @@
 
 	int timeout;
 	int retries;
+	struct device dev;	/* the adapter device */
 
 #ifdef CONFIG_PROC_FS 
 	/* No need to set this when you initialize the adapter          */
 	int inode;
 #endif /* def CONFIG_PROC_FS */
 };
+#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
 /*flags for the driver struct: */
 #define I2C_DF_NOTIFY	0x01		/* notify on bus (de/a)ttaches 	*/


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23               ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1111, 2003/03/13 12:16:52-08:00, greg@kroah.com

i2c: i2c-piix4.c: Clean up the ibm dma scan logic

Also export the is_unsafe_smbus variable, which is needed.


 arch/i386/kernel/dmi_scan.c    |    3 +++
 drivers/i2c/busses/i2c-piix4.c |   20 ++------------------
 2 files changed, 5 insertions(+), 18 deletions(-)


diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Thu Mar 13 16:57:17 2003
+++ b/arch/i386/kernel/dmi_scan.c	Thu Mar 13 16:57:17 2003
@@ -3,6 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/apm_bios.h>
 #include <linux/slab.h>
 #include <asm/io.h>
@@ -893,3 +894,5 @@
 	if(err == 0)
 		dmi_check_blacklist();
 }
+
+EXPORT_SYMBOL(is_unsafe_smbus);
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:17 2003
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:17 2003
@@ -28,7 +28,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/pci.h>
@@ -104,31 +103,18 @@
 
 static unsigned short piix4_smba = 0;
 
-#ifdef CONFIG_X86
 /*
  * Get DMI information.
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,34)
-void dmi_scan_mach(void);
-#endif
-
-static int __init ibm_dmi_probe(void)
+static int ibm_dmi_probe(void)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+#ifdef CONFIG_X86
 	extern int is_unsafe_smbus;
 	return is_unsafe_smbus;
 #else
-#define IBM_SIGNATURE		"IBM"
-	dmi_scan_mach();
-	if(dmi_ident[DMI_SYS_VENDOR] == NULL)
-		return 0;
-	if(strncmp(dmi_ident[DMI_SYS_VENDOR], IBM_SIGNATURE,
-	           strlen(IBM_SIGNATURE)) == 0)
-		return 1;
 	return 0;
 #endif
 }
-#endif
 
 static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id)
 {
@@ -141,7 +127,6 @@
 
 	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name);
 
-#ifdef CONFIG_X86
 	if(ibm_dmi_probe()) {
 		printk
 		  (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n");
@@ -150,7 +135,6 @@
 		 error_return = -EPERM;
 		 goto END;
 	}
-#endif
 
 /* Determine the address of the SMBus areas */
 	if (force_addr) {


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23             ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1110, 2003/03/13 11:59:13-08:00, greg@kroah.com

i2c: get i2c-piix4 driver to actually bind to a PCI device.


 drivers/i2c/busses/i2c-piix4.c |   99 +++++++++++++++++++++--------------------
 1 files changed, 52 insertions(+), 47 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:25 2003
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:25 2003
@@ -49,18 +49,6 @@
 	const char *name;
 };
 
-/* Note: We assume all devices are identical
-         to the Intel PIIX4; we only mention it during detection.   */
-
-static struct sd supported[] = {
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, 3, "PIIX4"},
-	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, 0, "OSB4"},
-	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5, 0, "CSB5"},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, 3, "440MX"},
-	{PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3, 0, "Victory66"},
-	{0, 0, 0, NULL}
-};
-
 /* PIIX4 SMBus address offsets */
 #define SMBHSTSTS (0 + piix4_smba)
 #define SMBHSLVSTS (1 + piix4_smba)
@@ -142,41 +130,16 @@
 }
 #endif
 
-/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
-   Note the differences between kernels with the old PCI BIOS interface and
-   newer kernels with the real PCI interface. In compat.h some things are
-   defined to make the transition easier. */
-int piix4_setup(void)
+static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id)
 {
 	int error_return = 0;
 	unsigned char temp;
-	struct sd *num = supported;
-	struct pci_dev *PIIX4_dev = NULL;
 
-	if (pci_present() == 0) {
-		error_return = -ENODEV;
-		goto END;
-	}
+	/* match up the function */
+	if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
+		return -ENODEV;
 
-	/* Look for a supported device/function */
-	do {
-		if((PIIX4_dev = pci_find_device(num->mfr, num->dev,
-					        PIIX4_dev))) {
-			if(PCI_FUNC(PIIX4_dev->devfn) != num->fn)
-				continue;
-			break;
-		}
-		PIIX4_dev = NULL;
-		num++;
-	} while (num->mfr);
-
-	if (PIIX4_dev == NULL) {
-		printk
-		  (KERN_ERR "i2c-piix4.o: Error: Can't detect PIIX4 or compatible device!\n");
-		 error_return = -ENODEV;
-		 goto END;
-	}
-	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", num->name);
+	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name);
 
 #ifdef CONFIG_X86
 	if(ibm_dmi_probe()) {
@@ -267,14 +230,14 @@
 
 
 /* Internally used pause function */
-void piix4_do_pause(unsigned int amount)
+static void piix4_do_pause(unsigned int amount)
 {
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(amount);
 }
 
 /* Another internally used function */
-int piix4_transaction(void)
+static int piix4_transaction(void)
 {
 	int temp;
 	int result = 0;
@@ -363,7 +326,7 @@
 }
 
 /* Return -1 on error. */
-s32 piix4_access(struct i2c_adapter * adap, u16 addr,
+static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
 		 unsigned short flags, char read_write,
 		 u8 command, int size, union i2c_smbus_data * data)
 {
@@ -456,7 +419,7 @@
 }
 
 
-u32 piix4_func(struct i2c_adapter *adapter)
+static u32 piix4_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
@@ -480,16 +443,58 @@
 
 
 static struct pci_device_id piix4_ids[] __devinitdata = {
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82371AB_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	3
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_SERVERWORKS,
+		.device =	PCI_DEVICE_ID_SERVERWORKS_OSB4,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_SERVERWORKS,
+		.device =	PCI_DEVICE_ID_SERVERWORKS_CSB5,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82443MX_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	3,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_EFAR,
+		.device =	PCI_DEVICE_ID_EFAR_SLC90E66_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
 	{ 0, }
 };
 
 static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	int retval;
+	
+	retval = piix4_setup(dev, id);
+	if (retval)
+		return retval;
 
 	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
 		piix4_smba);
 
-	i2c_add_adapter(&piix4_adapter);
+	retval = i2c_add_adapter(&piix4_adapter);
+
+	return retval;
 }
 
 static void __devexit piix4_remove(struct pci_dev *dev)


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23                 ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1112, 2003/03/13 12:26:39-08:00, greg@kroah.com

i2c: add i2c sysfs bus support.


 drivers/i2c/i2c-core.c |   33 ++++++++++++++++++++++++++++++---
 include/linux/i2c.h    |    3 +++
 2 files changed, 33 insertions(+), 3 deletions(-)


diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	Thu Mar 13 16:57:09 2003
+++ b/drivers/i2c/i2c-core.c	Thu Mar 13 16:57:09 2003
@@ -598,10 +598,37 @@
 {
 	remove_proc_entry("i2c",proc_bus);
 }
+#else
+static int __init i2cproc_init(void) { return 0; }
+static void __exit i2cproc_cleanup(void) { }
+#endif /* CONFIG_PROC_FS */
 
-module_init(i2cproc_init);
-module_exit(i2cproc_cleanup);
-#endif /* def CONFIG_PROC_FS */
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+struct bus_type i2c_bus_type = {
+	.name =		"i2c",
+	.match =	i2c_device_match,
+};
+
+
+static int __init i2c_init(void)
+{
+	bus_register(&i2c_bus_type);
+	return i2cproc_init();
+}
+
+static void __exit i2c_exit(void)
+{
+	i2cproc_cleanup();
+	bus_unregister(&i2c_bus_type);
+}
+
+module_init(i2c_init);
+module_exit(i2c_exit);
 
 /* ----------------------------------------------------
  * the functional interface to the i2c busses.
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Thu Mar 13 16:57:09 2003
+++ b/include/linux/i2c.h	Thu Mar 13 16:57:09 2003
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/i2c-id.h>
+#include <linux/device.h>	/* for struct device */
 #include <asm/semaphore.h>
 
 /* --- General options ------------------------------------------------	*/
@@ -143,6 +144,8 @@
 	 */
 	int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
 };
+
+extern struct bus_type i2c_bus_type;
 
 /*
  * i2c_client identifies a single device (i.e. chip) that is connected to an 


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23     ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com

i2c: get i2c-ali15x3 driver to actually bind to a PCI device.


 drivers/i2c/busses/i2c-ali15x3.c |   32 +++++++++-----------------------
 1 files changed, 9 insertions(+), 23 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:57:58 2003
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:57:58 2003
@@ -135,32 +135,11 @@
 
 static unsigned short ali15x3_smba = 0;
 
-/* Detect whether a ALI15X3 can be found, and initialize it, where necessary.
-   Note the differences between kernels with the old PCI BIOS interface and
-   newer kernels with the real PCI interface. In compat.h some things are
-   defined to make the transition easier. */
-int ali15x3_setup(void)
+int ali15x3_setup(struct pci_dev *ALI15X3_dev)
 {
 	u16 a;
 	unsigned char temp;
 
-	struct pci_dev *ALI15X3_dev;
-
-	/* First check whether we can access PCI at all */
-	if (pci_present() == 0) {
-		printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
-		return -ENODEV;
-	}
-
-	/* Look for the ALI15X3, M7101 device */
-	ALI15X3_dev = NULL;
-	ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
-				      PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
-	if (ALI15X3_dev == NULL) {
-		printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
-		return -ENODEV;
-	}
-
 /* Check the following things:
 	- SMB I/O address is initialized
 	- Device is enabled
@@ -534,12 +513,18 @@
 
 
 static struct pci_device_id ali15x3_ids[] __devinitdata = {
+	{
+	.vendor =	PCI_VENDOR_ID_AL,
+	.device =	PCI_DEVICE_ID_AL_M7101,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	},
 	{ 0, }
 };
 
 static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	if (ali15x3_setup()) {
+	if (ali15x3_setup(dev)) {
 		printk
 		    ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
 
@@ -549,6 +534,7 @@
 	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
 		ali15x3_smba);
 	i2c_add_adapter(&ali15x3_adapter);
+	return 0;
 }
 
 static void __devexit ali15x3_remove(struct pci_dev *dev)


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23                   ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1113, 2003/03/13 16:37:27-08:00, greg@kroah.com

driver core: Export the legacy_bus structure for drivers to use.


 drivers/base/platform.c |    3 ++-
 include/linux/device.h  |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)


diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	Thu Mar 13 16:57:00 2003
+++ b/drivers/base/platform.c	Thu Mar 13 16:57:00 2003
@@ -9,7 +9,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-static struct device legacy_bus = {
+struct device legacy_bus = {
 	.name		= "legacy bus",
 	.bus_id		= "legacy",
 };
@@ -75,5 +75,6 @@
 	return bus_register(&platform_bus_type);
 }
 
+EXPORT_SYMBOL(legacy_bus);
 EXPORT_SYMBOL(platform_device_register);
 EXPORT_SYMBOL(platform_device_unregister);
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Thu Mar 13 16:57:00 2003
+++ b/include/linux/device.h	Thu Mar 13 16:57:00 2003
@@ -366,6 +366,7 @@
 extern void platform_device_unregister(struct platform_device *);
 
 extern struct bus_type platform_bus_type;
+extern struct device legacy_bus;
 
 /* drivers/base/power.c */
 extern int device_suspend(u32 state, u32 level);


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
@ 2005-05-19  6:23           ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  0:55 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1109, 2003/03/13 11:52:26-08:00, greg@kroah.com

i2c: add bus driver for Intel PIIX4 devices

This is from the i2c CVS tree.


 drivers/i2c/busses/Kconfig     |   25 +
 drivers/i2c/busses/Makefile    |    1 
 drivers/i2c/busses/i2c-piix4.c |  529 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 554 insertions(+), 1 deletion(-)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:33 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:33 2003
@@ -55,7 +55,7 @@
 
 config I2C_I801
 	tristate "  Intel 801"
-	depends on I2C && I2C_PROC
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  801 family of mainboard I2C interfaces.  Specifically, the following
@@ -71,6 +71,29 @@
 	  say M here and read <file:Documentation/modules.txt>.
 
 	  The module will be called i2c-i801.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+
+config I2C_PIIX4
+	tristate "  Intel PIIX4"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  PIIX4 family of mainboard I2C interfaces.  Specifically, the following
+	  versions of the chipset is supported:
+	    Intel PIIX4
+	    Intel 440MX
+	    Serverworks OSB4
+	    Serverworks CSB5
+	    SMSC Victory66
+
+	  This can also be built as a module which can be inserted and removed 
+	  while the kernel is running.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  The module will be called i2c-piix4.
 
 	  You will also need the latest user-space utilties: you can find them
 	  in the lm_sensors package, which you can download at 
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:33 2003
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:33 2003
@@ -6,3 +6,4 @@
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
+obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:33 2003
@@ -0,0 +1,529 @@
+/*
+    piix4.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com>
+
+    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.
+*/
+
+/*
+   Supports:
+	Intel PIIX4, 440MX
+	Serverworks OSB4, CSB5
+	SMSC Victory66
+
+   Note: we assume there can only be one device, with one SMBus interface.
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/apm_bios.h>
+#include <asm/io.h>
+
+
+struct sd {
+	const unsigned short mfr;
+	const unsigned short dev;
+	const unsigned char fn;
+	const char *name;
+};
+
+/* Note: We assume all devices are identical
+         to the Intel PIIX4; we only mention it during detection.   */
+
+static struct sd supported[] = {
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, 3, "PIIX4"},
+	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, 0, "OSB4"},
+	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5, 0, "CSB5"},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, 3, "440MX"},
+	{PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3, 0, "Victory66"},
+	{0, 0, 0, NULL}
+};
+
+/* PIIX4 SMBus address offsets */
+#define SMBHSTSTS (0 + piix4_smba)
+#define SMBHSLVSTS (1 + piix4_smba)
+#define SMBHSTCNT (2 + piix4_smba)
+#define SMBHSTCMD (3 + piix4_smba)
+#define SMBHSTADD (4 + piix4_smba)
+#define SMBHSTDAT0 (5 + piix4_smba)
+#define SMBHSTDAT1 (6 + piix4_smba)
+#define SMBBLKDAT (7 + piix4_smba)
+#define SMBSLVCNT (8 + piix4_smba)
+#define SMBSHDWCMD (9 + piix4_smba)
+#define SMBSLVEVT (0xA + piix4_smba)
+#define SMBSLVDAT (0xC + piix4_smba)
+
+/* PCI Address Constants */
+#define SMBBA     0x090
+#define SMBHSTCFG 0x0D2
+#define SMBSLVC   0x0D3
+#define SMBSHDW1  0x0D4
+#define SMBSHDW2  0x0D5
+#define SMBREV    0x0D6
+
+/* Other settings */
+#define MAX_TIMEOUT 500
+#define  ENABLE_INT9 0
+
+/* PIIX4 constants */
+#define PIIX4_QUICK      0x00
+#define PIIX4_BYTE       0x04
+#define PIIX4_BYTE_DATA  0x08
+#define PIIX4_WORD_DATA  0x0C
+#define PIIX4_BLOCK_DATA 0x14
+
+/* insmod parameters */
+
+/* If force is set to anything different from 0, we forcibly enable the
+   PIIX4. DANGEROUS! */
+static int force = 0;
+MODULE_PARM(force, "i");
+MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the PIIX4 at the given address. VERY DANGEROUS! */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Forcibly enable the PIIX4 at the given address. "
+		 "EXTREMELY DANGEROUS!");
+
+static void piix4_do_pause(unsigned int amount);
+static int piix4_transaction(void);
+
+
+static unsigned short piix4_smba = 0;
+
+#ifdef CONFIG_X86
+/*
+ * Get DMI information.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,34)
+void dmi_scan_mach(void);
+#endif
+
+static int __init ibm_dmi_probe(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+	extern int is_unsafe_smbus;
+	return is_unsafe_smbus;
+#else
+#define IBM_SIGNATURE		"IBM"
+	dmi_scan_mach();
+	if(dmi_ident[DMI_SYS_VENDOR] == NULL)
+		return 0;
+	if(strncmp(dmi_ident[DMI_SYS_VENDOR], IBM_SIGNATURE,
+	           strlen(IBM_SIGNATURE)) == 0)
+		return 1;
+	return 0;
+#endif
+}
+#endif
+
+/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
+   Note the differences between kernels with the old PCI BIOS interface and
+   newer kernels with the real PCI interface. In compat.h some things are
+   defined to make the transition easier. */
+int piix4_setup(void)
+{
+	int error_return = 0;
+	unsigned char temp;
+	struct sd *num = supported;
+	struct pci_dev *PIIX4_dev = NULL;
+
+	if (pci_present() == 0) {
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	/* Look for a supported device/function */
+	do {
+		if((PIIX4_dev = pci_find_device(num->mfr, num->dev,
+					        PIIX4_dev))) {
+			if(PCI_FUNC(PIIX4_dev->devfn) != num->fn)
+				continue;
+			break;
+		}
+		PIIX4_dev = NULL;
+		num++;
+	} while (num->mfr);
+
+	if (PIIX4_dev == NULL) {
+		printk
+		  (KERN_ERR "i2c-piix4.o: Error: Can't detect PIIX4 or compatible device!\n");
+		 error_return = -ENODEV;
+		 goto END;
+	}
+	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", num->name);
+
+#ifdef CONFIG_X86
+	if(ibm_dmi_probe()) {
+		printk
+		  (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n");
+		printk
+		  (KERN_ERR "             your serial eeprom! Refusing to load module!\n");
+		 error_return = -EPERM;
+		 goto END;
+	}
+#endif
+
+/* Determine the address of the SMBus areas */
+	if (force_addr) {
+		piix4_smba = force_addr & 0xfff0;
+		force = 0;
+	} else {
+		pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
+		piix4_smba &= 0xfff0;
+		if(piix4_smba == 0) {
+			printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+			return -ENODEV;
+		}
+	}
+
+	if (check_region(piix4_smba, 8)) {
+		printk
+		    (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n",
+		     piix4_smba);
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
+/* If force_addr is set, we program the new address here. Just to make
+   sure, we disable the PIIX4 first. */
+	if (force_addr) {
+		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
+		pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
+		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
+		printk
+		    (KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new "
+		     "address %04x!\n", piix4_smba);
+	} else if ((temp & 1) == 0) {
+		if (force) {
+/* This should never need to be done, but has been noted that
+   many Dell machines have the SMBus interface on the PIIX4
+   disabled!? NOTE: This assumes I/O space and other allocations WERE
+   done by the Bios!  Don't complain if your hardware does weird 
+   things after enabling this. :') Check for Bios updates before
+   resorting to this.  */
+			pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
+					      temp | 1);
+			printk
+			    (KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY "
+			     "ENABLED!\n");
+		} else {
+			printk
+			    (KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n");
+			error_return = -ENODEV;
+			goto END;
+		}
+	}
+
+	/* Everything is happy, let's grab the memory and set things up. */
+	request_region(piix4_smba, 8, "piix4-smbus");
+
+#ifdef DEBUG
+	if ((temp & 0x0E) == 8)
+		printk
+		    (KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n");
+	else if ((temp & 0x0E) == 0)
+		printk
+		    (KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n");
+	else
+		printk
+		    (KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out "
+		     "of date)!\n");
+
+	pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
+	printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp);
+	printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba);
+#endif				/* DEBUG */
+
+      END:
+	return error_return;
+}
+
+
+/* Internally used pause function */
+void piix4_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+/* Another internally used function */
+int piix4_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n",
+		       temp);
+#endif
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+#ifdef DEBUG
+			printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
+#endif
+			return -1;
+		} else {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
+#endif
+		}
+	}
+
+	/* start the transaction by setting bit 6 */
+	outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
+
+	/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
+	do {
+		piix4_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+
+#ifdef DEBUG
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+		printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n");
+		result = -1;
+	}
+#endif
+
+	if (temp & 0x10) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+	if (temp & 0x08) {
+		result = -1;
+		printk
+		    (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n"
+		     "reset. (sorry!)\n");
+		/* Clock stops and slave is stuck in mid-transmission */
+	}
+
+	if (temp & 0x04) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
+#endif
+	}
+
+	if (inb_p(SMBHSTSTS) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+#ifdef DEBUG
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+		printk
+		    (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
+		     temp);
+	}
+	printk
+	    (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* Return -1 on error. */
+s32 piix4_access(struct i2c_adapter * adap, u16 addr,
+		 unsigned short flags, char read_write,
+		 u8 command, int size, union i2c_smbus_data * data)
+{
+	int i, len;
+
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		printk
+		    (KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n");
+		return -1;
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		size = PIIX4_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		size = PIIX4_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		size = PIIX4_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		size = PIIX4_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write == I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len < 0)
+				len = 0;
+			if (len > 32)
+				len = 32;
+			outb_p(len, SMBHSTDAT0);
+			i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+			for (i = 1; i <= len; i++)
+				outb_p(data->block[i], SMBBLKDAT);
+		}
+		size = PIIX4_BLOCK_DATA;
+		break;
+	}
+
+	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
+
+	if (piix4_transaction())	/* Error in transaction */
+		return -1;
+
+	if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
+		return 0;
+
+
+	switch (size) {
+	case PIIX4_BYTE:	/* Where is the result put? I assume here it is in
+				   SMBHSTDAT0 but it might just as well be in the
+				   SMBHSTCMD. No clue in the docs */
+
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case PIIX4_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case PIIX4_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	case PIIX4_BLOCK_DATA:
+		data->block[0] = inb_p(SMBHSTDAT0);
+		i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+		for (i = 1; i <= data->block[0]; i++)
+			data->block[i] = inb_p(SMBBLKDAT);
+		break;
+	}
+	return 0;
+}
+
+
+u32 piix4_func(struct i2c_adapter *adapter)
+{
+	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 struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= piix4_access,
+	.functionality	= piix4_func,
+};
+
+static struct i2c_adapter piix4_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id piix4_ids[] __devinitdata = {
+	{ 0, }
+};
+
+static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+
+	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
+		piix4_smba);
+
+	i2c_add_adapter(&piix4_adapter);
+}
+
+static void __devexit piix4_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&piix4_adapter);
+}
+
+
+static struct pci_driver piix4_driver = {
+	.name		= "piix4 smbus",
+	.id_table	= piix4_ids,
+	.probe		= piix4_probe,
+	.remove		= __devexit_p(piix4_remove),
+};
+
+static int __init i2c_piix4_init(void)
+{
+	printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&piix4_driver);
+}
+
+
+static void __exit i2c_piix4_exit(void)
+{
+	pci_unregister_driver(&piix4_driver);
+	release_region(piix4_smba, 8);
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("PIIX4 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_piix4_init);
+module_exit(i2c_piix4_exit);


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23   ` Greg KH
@ 2005-05-19  6:23     ` Christoph Hellwig
  -1 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2003-03-14  8:19 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> +/* Detect whether a ALI15X3 can be found, and initialize it, where necessary.
> +   Note the differences between kernels with the old PCI BIOS interface and
> +   newer kernels with the real PCI interface. In compat.h some things are
> +   defined to make the transition easier. */

This comment seems a bit outdated..

> +int ali15x3_setup(void)

Should be static like everything in this file (and merged into
ali15x3_probe anyway).

> +{
> +	u16 a;
> +	unsigned char temp;
> +
> +	struct pci_dev *ALI15X3_dev;
> +
> +	/* First check whether we can access PCI at all */
> +	if (pci_present() == 0) {
> +		printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
> +		return -ENODEV;
> +	}

You're calling this from pci_driver->probe, so you will never get
here without PCI hardware.

> +	/* Look for the ALI15X3, M7101 device */
> +	ALI15X3_dev = NULL;
> +	ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
> +				      PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
> +	if (ALI15X3_dev == NULL) {
> +		printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
> +		return -ENODEV;
> +	}

Calling pci_find_device in ->probe looks buggy to me.  What are you
trying to do?

> +/* Is SMB Host controller enabled? */
> +	pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
> +	if ((temp & 1) == 0) {

What about proper indentation for the comments?

> +/* Internally used pause function */
> +void ali15x3_do_pause(unsigned int amount)
> +{
> +	current->state = TASK_INTERRUPTIBLE;
> +	schedule_timeout(amount);
> +}

I think this should be moved to linux/kernel.h as delay() - I've seen
it duplicated in so much code (including XFS)

> +#ifdef DEBUG
> +	printk
> +	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
> +	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
> +	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
> +	     inb_p(SMBHSTDAT1));
> +#endif

use pr_debug() here.

> +static struct pci_device_id ali15x3_ids[] __devinitdata = {
> +	{ 0, }
> +};

Umm?


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23     ` Greg KH
@ 2005-05-19  6:23       ` Christoph Hellwig
  -1 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2003-03-14  8:21 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com
> 
> i2c: get i2c-ali15x3 driver to actually bind to a PCI device.

OOPS, should take a look at all patches first before complaining :)

>  static struct pci_device_id ali15x3_ids[] __devinitdata = {
> +	{
> +	.vendor =	PCI_VENDOR_ID_AL,
> +	.device =	PCI_DEVICE_ID_AL_M7101,
> +	.subvendor =	PCI_ANY_ID,
> +	.subdevice =	PCI_ANY_ID,
> +	},

The indentation looks a bit b0rked..


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23       ` Greg KH
@ 2005-05-19  6:23         ` Christoph Hellwig
  -1 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2003-03-14  8:28 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> +#include <linux/i2c.h>
> +#include <asm/io.h>
> +
> +MODULE_LICENSE("GPL");

This should be at the bottom of the file with the other MODULE_* stuff

> +#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
> +#define HAVE_PEC
> +#endif

Needs more explanation.

> +
> +#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS
> +#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS	0x2483
> +#endif
> +
> +#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS
> +#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS	0x24C3
> +#endif

Should go to pci_ids.h

> +
> +static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
> +                          PCI_DEVICE_ID_INTEL_82801AB_3,
> +                          PCI_DEVICE_ID_INTEL_82801BA_2,
> +			  PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
> +			  PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
> +                          0 };

Shouldn't be required with new-style pci probing.

> +static int force_addr = 0;
> +MODULE_PARM(force_addr, "i");
> +MODULE_PARM_DESC(force_addr,
> +		 "Forcibly enable the I801 at the given address. "
> +		 "EXTREMELY DANGEROUS!");

What about using Rusty's new module parameter stuff?

> +static unsigned short i801_smba = 0;
> +static struct pci_dev *I801_dev = NULL;
> +static int isich4 = 0;

This is in .bss..

> +/* Detect whether a I801 can be found, and initialize it, where necessary.
> +   Note the differences between kernels with the old PCI BIOS interface and
> +   newer kernels with the real PCI interface. In compat.h some things are
> +   defined to make the transition easier. */
> +int i801_setup(void)

Merge with caller, comment is b0rked.

> +{
> +	int error_return = 0;
> +	int *num = supported;
> +	unsigned char temp;
> +
> +	/* First check whether we can access PCI at all */
> +	if (pci_present() == 0) {
> +		printk(KERN_WARNING "i2c-i801.o: Error: No PCI-bus found!\n");
> +		error_return = -ENODEV;
> +		goto END;
> +	}

END is a bad name for a label.  

> +	/* Look for each chip */
> +	/* Note: we keep on searching until we have found 'function 3' */
> +	I801_dev = NULL;
> +	do {
> +		if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
> +					      *num, I801_dev))) {
> +			if(PCI_FUNC(I801_dev->devfn) != 3)
> +				continue;
> +			break;
> +		}
> +		num++;
> +	} while (*num != 0);

You already changed it to new-style pci probing in the next patch, didn't
you?

> +	if (check_region(i801_smba, (isich4 ? 16 : 8))) {

no way!

> +int i801_transaction(void)

static..

> +	int temp;
> +	int result = 0;
> +	int timeout = 0;
> +
> +#ifdef DEBUG
> +	printk
> +	    (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
> +	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
> +	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
> +#endif

pr_debug

> +		temp = inb_p(SMBHSTSTS);
> +                if (i == 1) {
> +                    /* Erronenous conditions before transaction: 
> +                     * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
> +                    errmask=0x9f; 
> +                } else {
> +                    /* Erronenous conditions during transaction: 
> +                     * Failed, Bus_Err, Dev_Err, Intr */
> +                    errmask=0x1e; 
> +                }

Indentation look b0rked.


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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23       ` Christoph Hellwig
@ 2005-05-19  6:23         ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  8:53 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, sensors

On Fri, Mar 14, 2003 at 08:21:42AM +0000, Christoph Hellwig wrote:
> On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> > ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com
> > 
> > i2c: get i2c-ali15x3 driver to actually bind to a PCI device.
> 
> OOPS, should take a look at all patches first before complaining :)

Heh :)

Yes, for the first changeset I just took the cvs version of the driver
and added it.

Then I went and made the driver work, and started to clean it up.  These
drivers still need a lot of cleanup (static, printk, indentation in
places, etc.) and I'll be doing it.  This is a work in progress.  I
wanted to make baby steps with these things and not just do one
changeset with a description that said:
	Took cvs version of driver and cleaned up everything

I'm trying to bridge the gap between the sensor developers and the
kernel group.  Hopefully by working this way it will help integrate them
more into the kernel community, and get these drivers whipped into
shape.

thanks for looking these over.

greg k-h

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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23     ` Christoph Hellwig
@ 2005-05-19  6:23       ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-14  8:56 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, sensors

On Fri, Mar 14, 2003 at 08:19:04AM +0000, Christoph Hellwig wrote:
> > +/* Internally used pause function */
> > +void ali15x3_do_pause(unsigned int amount)
> > +{
> > +	current->state = TASK_INTERRUPTIBLE;
> > +	schedule_timeout(amount);
> > +}
> 
> I think this should be moved to linux/kernel.h as delay() - I've seen
> it duplicated in so much code (including XFS)

I'll move this.  I think I have this in the usb.h header file too :)

> > +#ifdef DEBUG
> > +	printk
> > +	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
> > +	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
> > +	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
> > +	     inb_p(SMBHSTDAT1));
> > +#endif
> 
> use pr_debug() here.

In the next round of patches I'm using dev_dbg() and other dev_*
functions for the printk calls, now that we have device support for the
adapters.

thanks,

greg k-h

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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23                     ` Greg KH
@ 2005-05-19  6:23                       ` Vojtech Pavlik
  -1 siblings, 0 replies; 47+ messages in thread
From: Vojtech Pavlik @ 2003-03-15  9:49 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:

> diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
> --- a/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
> +++ b/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
 		goto out_release_region;
> @@ -389,7 +392,7 @@
>  }
>  
>  static struct pci_driver amd8111_driver = {
> -	.name		= "amd8111 smbus 2.0",
> +	.name		= "amd8111 smbus",
>  	.id_table	= amd8111_ids,
>  	.probe		= amd8111_probe,
>  	.remove		= __devexit_p(amd8111_remove),

The 2.0 was quite intentional in the .name, because the 8111 has *two*
SMBus busses, one SMBus 1.1 and one SMBus 2.0. This driver is only for
the 2.0 SMBus controller.

-- 
Vojtech Pavlik
SuSE Labs

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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23                       ` Vojtech Pavlik
@ 2005-05-19  6:23                         ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2003-03-15 21:46 UTC (permalink / raw)
  To: Vojtech Pavlik; +Cc: linux-kernel, sensors

On Sat, Mar 15, 2003 at 10:49:01AM +0100, Vojtech Pavlik wrote:
> On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> >  static struct pci_driver amd8111_driver = {
> > -	.name		= "amd8111 smbus 2.0",
> > +	.name		= "amd8111 smbus",
> 
> The 2.0 was quite intentional in the .name, because the 8111 has *two*
> SMBus busses, one SMBus 1.1 and one SMBus 2.0. This driver is only for
> the 2.0 SMBus controller.

Ah, I removed the "2.0" portion because it was larger than the 16
character limit for pci driver names (it shows up in sysfs garbled if
it's bigger).

Would "amd8111 smbus 2" be an ok name?

thanks,

greg k-h

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

* Re: [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23                         ` Greg KH
@ 2005-05-19  6:23                           ` Vojtech Pavlik
  -1 siblings, 0 replies; 47+ messages in thread
From: Vojtech Pavlik @ 2003-03-15 22:06 UTC (permalink / raw)
  To: Greg KH; +Cc: Vojtech Pavlik, linux-kernel, sensors

On Sat, Mar 15, 2003 at 01:46:23PM -0800, Greg KH wrote:
> On Sat, Mar 15, 2003 at 10:49:01AM +0100, Vojtech Pavlik wrote:
> > On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> > >  static struct pci_driver amd8111_driver = {
> > > -	.name		= "amd8111 smbus 2.0",
> > > +	.name		= "amd8111 smbus",
> > 
> > The 2.0 was quite intentional in the .name, because the 8111 has *two*
> > SMBus busses, one SMBus 1.1 and one SMBus 2.0. This driver is only for
> > the 2.0 SMBus controller.
> 
> Ah, I removed the "2.0" portion because it was larger than the 16
> character limit for pci driver names (it shows up in sysfs garbled if
> it's bigger).
> 
> Would "amd8111 smbus 2" be an ok name?

Yes.

-- 
Vojtech Pavlik
SuSE Labs

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23         ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1108, 2003/03/13 11:38:03-08:00, greg@kroah.com

i2c: get i2c-i801 driver to actually bind to a PCI device.


 drivers/i2c/busses/i2c-i801.c |   74 +++++++++++++++++++++---------------------
 1 files changed, 38 insertions(+), 36 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:57:41 2003
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:57:41 2003
@@ -128,49 +128,21 @@
 static int i801_block_transaction(union i2c_smbus_data *data,
 				  char read_write, int command);
 
+static unsigned short i801_smba;
+static struct pci_dev *I801_dev;
+static int isich4;
 
-
-
-static unsigned short i801_smba = 0;
-static struct pci_dev *I801_dev = NULL;
-static int isich4 = 0;
-
-/* Detect whether a I801 can be found, and initialize it, where necessary.
-   Note the differences between kernels with the old PCI BIOS interface and
-   newer kernels with the real PCI interface. In compat.h some things are
-   defined to make the transition easier. */
-int i801_setup(void)
+static int i801_setup(struct pci_dev *dev)
 {
 	int error_return = 0;
 	int *num = supported;
 	unsigned char temp;
 
-	/* First check whether we can access PCI at all */
-	if (pci_present() = 0) {
-		printk(KERN_WARNING "i2c-i801.o: Error: No PCI-bus found!\n");
-		error_return = -ENODEV;
-		goto END;
-	}
-
-	/* Look for each chip */
 	/* Note: we keep on searching until we have found 'function 3' */
-	I801_dev = NULL;
-	do {
-		if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
-					      *num, I801_dev))) {
-			if(PCI_FUNC(I801_dev->devfn) != 3)
-				continue;
-			break;
-		}
-		num++;
-	} while (*num != 0);
+	if(PCI_FUNC(dev->devfn) != 3)
+		return -ENODEV;
 
-	if (I801_dev = NULL) {
-		printk
-		    (KERN_WARNING "i2c-i801.o: Error: Can't detect I801, function 3!\n");
-		error_return = -ENODEV;
-		goto END;
-	}
+	I801_dev = dev;
 	isich4 = *num = PCI_DEVICE_ID_INTEL_82801DB_SMBUS;
 
 /* Determine the address of the SMBus areas */
@@ -658,13 +630,43 @@
 
 
 static struct pci_device_id i801_ids[] __devinitdata = {
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801AA_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801AB_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801BA_2,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+	},
 	{ 0, }
 };
 
 static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
 
-	if (i801_setup()) {
+	if (i801_setup(dev)) {
 		printk
 		    (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n");
 		return -ENODEV;

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23     ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com

i2c: get i2c-ali15x3 driver to actually bind to a PCI device.


 drivers/i2c/busses/i2c-ali15x3.c |   32 +++++++++-----------------------
 1 files changed, 9 insertions(+), 23 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:57:58 2003
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:57:58 2003
@@ -135,32 +135,11 @@
 
 static unsigned short ali15x3_smba = 0;
 
-/* Detect whether a ALI15X3 can be found, and initialize it, where necessary.
-   Note the differences between kernels with the old PCI BIOS interface and
-   newer kernels with the real PCI interface. In compat.h some things are
-   defined to make the transition easier. */
-int ali15x3_setup(void)
+int ali15x3_setup(struct pci_dev *ALI15X3_dev)
 {
 	u16 a;
 	unsigned char temp;
 
-	struct pci_dev *ALI15X3_dev;
-
-	/* First check whether we can access PCI at all */
-	if (pci_present() = 0) {
-		printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
-		return -ENODEV;
-	}
-
-	/* Look for the ALI15X3, M7101 device */
-	ALI15X3_dev = NULL;
-	ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
-				      PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
-	if (ALI15X3_dev = NULL) {
-		printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
-		return -ENODEV;
-	}
-
 /* Check the following things:
 	- SMB I/O address is initialized
 	- Device is enabled
@@ -534,12 +513,18 @@
 
 
 static struct pci_device_id ali15x3_ids[] __devinitdata = {
+	{
+	.vendor =	PCI_VENDOR_ID_AL,
+	.device =	PCI_DEVICE_ID_AL_M7101,
+	.subvendor =	PCI_ANY_ID,
+	.subdevice =	PCI_ANY_ID,
+	},
 	{ 0, }
 };
 
 static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
-	if (ali15x3_setup()) {
+	if (ali15x3_setup(dev)) {
 		printk
 		    ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
 
@@ -549,6 +534,7 @@
 	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
 		ali15x3_smba);
 	i2c_add_adapter(&ali15x3_adapter);
+	return 0;
 }
 
 static void __devexit ali15x3_remove(struct pci_dev *dev)

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23           ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1109, 2003/03/13 11:52:26-08:00, greg@kroah.com

i2c: add bus driver for Intel PIIX4 devices

This is from the i2c CVS tree.


 drivers/i2c/busses/Kconfig     |   25 +
 drivers/i2c/busses/Makefile    |    1 
 drivers/i2c/busses/i2c-piix4.c |  529 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 554 insertions(+), 1 deletion(-)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:33 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:33 2003
@@ -55,7 +55,7 @@
 
 config I2C_I801
 	tristate "  Intel 801"
-	depends on I2C && I2C_PROC
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
 	help
 	  If you say yes to this option, support will be included for the Intel
 	  801 family of mainboard I2C interfaces.  Specifically, the following
@@ -71,6 +71,29 @@
 	  say M here and read <file:Documentation/modules.txt>.
 
 	  The module will be called i2c-i801.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+
+config I2C_PIIX4
+	tristate "  Intel PIIX4"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  PIIX4 family of mainboard I2C interfaces.  Specifically, the following
+	  versions of the chipset is supported:
+	    Intel PIIX4
+	    Intel 440MX
+	    Serverworks OSB4
+	    Serverworks CSB5
+	    SMSC Victory66
+
+	  This can also be built as a module which can be inserted and removed 
+	  while the kernel is running.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  The module will be called i2c-piix4.
 
 	  You will also need the latest user-space utilties: you can find them
 	  in the lm_sensors package, which you can download at 
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:33 2003
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:33 2003
@@ -6,3 +6,4 @@
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
 obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
+obj-$(CONFIG_I2C_PIIX4)		+= i2c-piix4.o
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:33 2003
@@ -0,0 +1,529 @@
+/*
+    piix4.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com>
+
+    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.
+*/
+
+/*
+   Supports:
+	Intel PIIX4, 440MX
+	Serverworks OSB4, CSB5
+	SMSC Victory66
+
+   Note: we assume there can only be one device, with one SMBus interface.
+*/
+
+#include <linux/version.h>
+#include <linux/module.h>
+#include <linux/config.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/apm_bios.h>
+#include <asm/io.h>
+
+
+struct sd {
+	const unsigned short mfr;
+	const unsigned short dev;
+	const unsigned char fn;
+	const char *name;
+};
+
+/* Note: We assume all devices are identical
+         to the Intel PIIX4; we only mention it during detection.   */
+
+static struct sd supported[] = {
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, 3, "PIIX4"},
+	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, 0, "OSB4"},
+	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5, 0, "CSB5"},
+	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, 3, "440MX"},
+	{PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3, 0, "Victory66"},
+	{0, 0, 0, NULL}
+};
+
+/* PIIX4 SMBus address offsets */
+#define SMBHSTSTS (0 + piix4_smba)
+#define SMBHSLVSTS (1 + piix4_smba)
+#define SMBHSTCNT (2 + piix4_smba)
+#define SMBHSTCMD (3 + piix4_smba)
+#define SMBHSTADD (4 + piix4_smba)
+#define SMBHSTDAT0 (5 + piix4_smba)
+#define SMBHSTDAT1 (6 + piix4_smba)
+#define SMBBLKDAT (7 + piix4_smba)
+#define SMBSLVCNT (8 + piix4_smba)
+#define SMBSHDWCMD (9 + piix4_smba)
+#define SMBSLVEVT (0xA + piix4_smba)
+#define SMBSLVDAT (0xC + piix4_smba)
+
+/* PCI Address Constants */
+#define SMBBA     0x090
+#define SMBHSTCFG 0x0D2
+#define SMBSLVC   0x0D3
+#define SMBSHDW1  0x0D4
+#define SMBSHDW2  0x0D5
+#define SMBREV    0x0D6
+
+/* Other settings */
+#define MAX_TIMEOUT 500
+#define  ENABLE_INT9 0
+
+/* PIIX4 constants */
+#define PIIX4_QUICK      0x00
+#define PIIX4_BYTE       0x04
+#define PIIX4_BYTE_DATA  0x08
+#define PIIX4_WORD_DATA  0x0C
+#define PIIX4_BLOCK_DATA 0x14
+
+/* insmod parameters */
+
+/* If force is set to anything different from 0, we forcibly enable the
+   PIIX4. DANGEROUS! */
+static int force = 0;
+MODULE_PARM(force, "i");
+MODULE_PARM_DESC(force, "Forcibly enable the PIIX4. DANGEROUS!");
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the PIIX4 at the given address. VERY DANGEROUS! */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Forcibly enable the PIIX4 at the given address. "
+		 "EXTREMELY DANGEROUS!");
+
+static void piix4_do_pause(unsigned int amount);
+static int piix4_transaction(void);
+
+
+static unsigned short piix4_smba = 0;
+
+#ifdef CONFIG_X86
+/*
+ * Get DMI information.
+ */
+#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,34)
+void dmi_scan_mach(void);
+#endif
+
+static int __init ibm_dmi_probe(void)
+{
+#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+	extern int is_unsafe_smbus;
+	return is_unsafe_smbus;
+#else
+#define IBM_SIGNATURE		"IBM"
+	dmi_scan_mach();
+	if(dmi_ident[DMI_SYS_VENDOR] = NULL)
+		return 0;
+	if(strncmp(dmi_ident[DMI_SYS_VENDOR], IBM_SIGNATURE,
+	           strlen(IBM_SIGNATURE)) = 0)
+		return 1;
+	return 0;
+#endif
+}
+#endif
+
+/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
+   Note the differences between kernels with the old PCI BIOS interface and
+   newer kernels with the real PCI interface. In compat.h some things are
+   defined to make the transition easier. */
+int piix4_setup(void)
+{
+	int error_return = 0;
+	unsigned char temp;
+	struct sd *num = supported;
+	struct pci_dev *PIIX4_dev = NULL;
+
+	if (pci_present() = 0) {
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	/* Look for a supported device/function */
+	do {
+		if((PIIX4_dev = pci_find_device(num->mfr, num->dev,
+					        PIIX4_dev))) {
+			if(PCI_FUNC(PIIX4_dev->devfn) != num->fn)
+				continue;
+			break;
+		}
+		PIIX4_dev = NULL;
+		num++;
+	} while (num->mfr);
+
+	if (PIIX4_dev = NULL) {
+		printk
+		  (KERN_ERR "i2c-piix4.o: Error: Can't detect PIIX4 or compatible device!\n");
+		 error_return = -ENODEV;
+		 goto END;
+	}
+	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", num->name);
+
+#ifdef CONFIG_X86
+	if(ibm_dmi_probe()) {
+		printk
+		  (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n");
+		printk
+		  (KERN_ERR "             your serial eeprom! Refusing to load module!\n");
+		 error_return = -EPERM;
+		 goto END;
+	}
+#endif
+
+/* Determine the address of the SMBus areas */
+	if (force_addr) {
+		piix4_smba = force_addr & 0xfff0;
+		force = 0;
+	} else {
+		pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
+		piix4_smba &= 0xfff0;
+		if(piix4_smba = 0) {
+			printk(KERN_ERR "i2c-piix4.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+			return -ENODEV;
+		}
+	}
+
+	if (check_region(piix4_smba, 8)) {
+		printk
+		    (KERN_ERR "i2c-piix4.o: SMB region 0x%x already in use!\n",
+		     piix4_smba);
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
+/* If force_addr is set, we program the new address here. Just to make
+   sure, we disable the PIIX4 first. */
+	if (force_addr) {
+		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp & 0xfe);
+		pci_write_config_word(PIIX4_dev, SMBBA, piix4_smba);
+		pci_write_config_byte(PIIX4_dev, SMBHSTCFG, temp | 0x01);
+		printk
+		    (KERN_INFO "i2c-piix4.o: WARNING: SMBus interface set to new "
+		     "address %04x!\n", piix4_smba);
+	} else if ((temp & 1) = 0) {
+		if (force) {
+/* This should never need to be done, but has been noted that
+   many Dell machines have the SMBus interface on the PIIX4
+   disabled!? NOTE: This assumes I/O space and other allocations WERE
+   done by the Bios!  Don't complain if your hardware does weird 
+   things after enabling this. :') Check for Bios updates before
+   resorting to this.  */
+			pci_write_config_byte(PIIX4_dev, SMBHSTCFG,
+					      temp | 1);
+			printk
+			    (KERN_NOTICE "i2c-piix4.o: WARNING: SMBus interface has been FORCEFULLY "
+			     "ENABLED!\n");
+		} else {
+			printk
+			    (KERN_ERR "i2c-piix4.o: Host SMBus controller not enabled!\n");
+			error_return = -ENODEV;
+			goto END;
+		}
+	}
+
+	/* Everything is happy, let's grab the memory and set things up. */
+	request_region(piix4_smba, 8, "piix4-smbus");
+
+#ifdef DEBUG
+	if ((temp & 0x0E) = 8)
+		printk
+		    (KERN_DEBUG "i2c-piix4.o: Using Interrupt 9 for SMBus.\n");
+	else if ((temp & 0x0E) = 0)
+		printk
+		    (KERN_DEBUG "i2c-piix4.o: Using Interrupt SMI# for SMBus.\n");
+	else
+		printk
+		    (KERN_ERR "i2c-piix4.o: Illegal Interrupt configuration (or code out "
+		     "of date)!\n");
+
+	pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
+	printk(KERN_DEBUG "i2c-piix4.o: SMBREV = 0x%X\n", temp);
+	printk(KERN_DEBUG "i2c-piix4.o: SMBA = 0x%X\n", piix4_smba);
+#endif				/* DEBUG */
+
+      END:
+	return error_return;
+}
+
+
+/* Internally used pause function */
+void piix4_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+/* Another internally used function */
+int piix4_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-piix4.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-piix4.o: SMBus busy (%02x). Resetting... \n",
+		       temp);
+#endif
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+#ifdef DEBUG
+			printk(KERN_ERR "i2c-piix4.o: Failed! (%02x)\n", temp);
+#endif
+			return -1;
+		} else {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-piix4.o: Successfull!\n");
+#endif
+		}
+	}
+
+	/* start the transaction by setting bit 6 */
+	outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
+
+	/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
+	do {
+		piix4_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+
+#ifdef DEBUG
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+		printk(KERN_ERR "i2c-piix4.o: SMBus Timeout!\n");
+		result = -1;
+	}
+#endif
+
+	if (temp & 0x10) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_ERR "i2c-piix4.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+	if (temp & 0x08) {
+		result = -1;
+		printk
+		    (KERN_ERR "i2c-piix4.o: Bus collision! SMBus may be locked until next hard\n"
+		     "reset. (sorry!)\n");
+		/* Clock stops and slave is stuck in mid-transmission */
+	}
+
+	if (temp & 0x04) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_ERR "i2c-piix4.o: Error: no response!\n");
+#endif
+	}
+
+	if (inb_p(SMBHSTSTS) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+#ifdef DEBUG
+	if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
+		printk
+		    (KERN_ERR "i2c-piix4.o: Failed reset at end of transaction (%02x)\n",
+		     temp);
+	}
+	printk
+	    (KERN_DEBUG "i2c-piix4.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* Return -1 on error. */
+s32 piix4_access(struct i2c_adapter * adap, u16 addr,
+		 unsigned short flags, char read_write,
+		 u8 command, int size, union i2c_smbus_data * data)
+{
+	int i, len;
+
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		printk
+		    (KERN_ERR "i2c-piix4.o: I2C_SMBUS_PROC_CALL not supported!\n");
+		return -1;
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		size = PIIX4_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write = I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		size = PIIX4_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		size = PIIX4_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		size = PIIX4_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len < 0)
+				len = 0;
+			if (len > 32)
+				len = 32;
+			outb_p(len, SMBHSTDAT0);
+			i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+			for (i = 1; i <= len; i++)
+				outb_p(data->block[i], SMBBLKDAT);
+		}
+		size = PIIX4_BLOCK_DATA;
+		break;
+	}
+
+	outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
+
+	if (piix4_transaction())	/* Error in transaction */
+		return -1;
+
+	if ((read_write = I2C_SMBUS_WRITE) || (size = PIIX4_QUICK))
+		return 0;
+
+
+	switch (size) {
+	case PIIX4_BYTE:	/* Where is the result put? I assume here it is in
+				   SMBHSTDAT0 but it might just as well be in the
+				   SMBHSTCMD. No clue in the docs */
+
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case PIIX4_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case PIIX4_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	case PIIX4_BLOCK_DATA:
+		data->block[0] = inb_p(SMBHSTDAT0);
+		i = inb_p(SMBHSTCNT);	/* Reset SMBBLKDAT */
+		for (i = 1; i <= data->block[0]; i++)
+			data->block[i] = inb_p(SMBBLKDAT);
+		break;
+	}
+	return 0;
+}
+
+
+u32 piix4_func(struct i2c_adapter *adapter)
+{
+	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 struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= piix4_access,
+	.functionality	= piix4_func,
+};
+
+static struct i2c_adapter piix4_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_PIIX4,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id piix4_ids[] __devinitdata = {
+	{ 0, }
+};
+
+static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+
+	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
+		piix4_smba);
+
+	i2c_add_adapter(&piix4_adapter);
+}
+
+static void __devexit piix4_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&piix4_adapter);
+}
+
+
+static struct pci_driver piix4_driver = {
+	.name		= "piix4 smbus",
+	.id_table	= piix4_ids,
+	.probe		= piix4_probe,
+	.remove		= __devexit_p(piix4_remove),
+};
+
+static int __init i2c_piix4_init(void)
+{
+	printk("i2c-piix4.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&piix4_driver);
+}
+
+
+static void __exit i2c_piix4_exit(void)
+{
+	pci_unregister_driver(&piix4_driver);
+	release_region(piix4_smba, 8);
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl> and Philip Edelbrock <phil@netroedge.com>");
+MODULE_DESCRIPTION("PIIX4 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_piix4_init);
+module_exit(i2c_piix4_exit);

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23                     ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1114, 2003/03/13 16:39:40-08:00, greg@kroah.com

i2c: add driver model support to i2c adapter drivers


 drivers/i2c/busses/i2c-ali15x3.c |    6 ++++--
 drivers/i2c/busses/i2c-amd756.c  |    3 +++
 drivers/i2c/busses/i2c-amd8111.c |    5 ++++-
 drivers/i2c/busses/i2c-i801.c    |    5 ++++-
 drivers/i2c/busses/i2c-piix4.c   |    3 +++
 drivers/i2c/i2c-core.c           |   13 +++++++++++++
 include/linux/i2c.h              |    2 ++
 7 files changed, 33 insertions(+), 4 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- a/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:56:52 2003
@@ -531,10 +531,12 @@
 		return -ENODEV;
 	}
 
+	/* set up the driverfs linkage to our parent device */
+	ali15x3_adapter.dev.parent = &dev->dev;
+
 	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
 		ali15x3_smba);
-	i2c_add_adapter(&ali15x3_adapter);
-	return 0;
+	return i2c_add_adapter(&ali15x3_adapter);
 }
 
 static void __devexit ali15x3_remove(struct pci_dev *dev)
diff -Nru a/drivers/i2c/busses/i2c-amd756.c b/drivers/i2c/busses/i2c-amd756.c
--- a/drivers/i2c/busses/i2c-amd756.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-amd756.c	Thu Mar 13 16:56:52 2003
@@ -375,6 +375,9 @@
 	printk(KERN_DEBUG DRV_NAME ": AMD756_smba = 0x%X\n", amd756_ioport);
 #endif
 
+	/* set up the driverfs linkage to our parent device */
+	amd756_adapter.dev.parent = &pdev->dev;
+
 	sprintf(amd756_adapter.name,
 		"SMBus AMD75x adapter at %04x", amd756_ioport);
 
diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
--- a/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
@@ -363,6 +363,9 @@
 	smbus->adapter.algo = &smbus_algorithm;
 	smbus->adapter.algo_data = smbus;
 
+	/* set up the driverfs linkage to our parent device */
+	smbus->adapter.dev.parent = &dev->dev;
+
 	error = i2c_add_adapter(&smbus->adapter);
 	if (error)
 		goto out_release_region;
@@ -389,7 +392,7 @@
 }
 
 static struct pci_driver amd8111_driver = {
-	.name		= "amd8111 smbus 2.0",
+	.name		= "amd8111 smbus",
 	.id_table	= amd8111_ids,
 	.probe		= amd8111_probe,
 	.remove		= __devexit_p(amd8111_remove),
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- a/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:56:52 2003
@@ -672,9 +672,12 @@
 		return -ENODEV;
 	}
 
+	/* set up the driverfs linkage to our parent device */
+	i801_adapter.dev.parent = &dev->dev;
+
 	sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
 		i801_smba);
-	i2c_add_adapter(&i801_adapter);
+	return i2c_add_adapter(&i801_adapter);
 }
 
 static void __devexit i801_remove(struct pci_dev *dev)
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:56:52 2003
@@ -473,6 +473,9 @@
 	if (retval)
 		return retval;
 
+	/* set up the driverfs linkage to our parent device */
+	piix4_adapter.dev.parent = &dev->dev;
+
 	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
 		piix4_smba);
 
diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	Thu Mar 13 16:56:52 2003
+++ b/drivers/i2c/i2c-core.c	Thu Mar 13 16:56:52 2003
@@ -87,6 +87,16 @@
 	init_MUTEX(&adap->bus);
 	init_MUTEX(&adap->list);
 
+	/* Add the adapter to the driver core.
+	 * If the parent pointer is not set up,
+	 * we add this adapter to the legacy bus.
+	 */
+	if (adap->dev.parent = NULL)
+		adap->dev.parent = &legacy_bus;
+	sprintf(adap->dev.bus_id, "i2c-%d", i);
+	strcpy(adap->dev.name, "i2c controller");
+	device_register(&adap->dev);
+
 	/* inform drivers of new adapters */
 	for (j=0;j<I2C_DRIVER_MAX;j++)
 		if (drivers[j]!=NULL && 
@@ -153,6 +163,9 @@
 	}
 
 	i2cproc_remove(i);
+
+	/* clean up the sysfs representation */
+	device_unregister(&adap->dev);
 
 	adapters[i] = NULL;
 
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Thu Mar 13 16:56:52 2003
+++ b/include/linux/i2c.h	Thu Mar 13 16:56:52 2003
@@ -231,12 +231,14 @@
 
 	int timeout;
 	int retries;
+	struct device dev;	/* the adapter device */
 
 #ifdef CONFIG_PROC_FS 
 	/* No need to set this when you initialize the adapter          */
 	int inode;
 #endif /* def CONFIG_PROC_FS */
 };
+#define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev)
 
 /*flags for the driver struct: */
 #define I2C_DF_NOTIFY	0x01		/* notify on bus (de/a)ttaches 	*/

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23                   ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1113, 2003/03/13 16:37:27-08:00, greg@kroah.com

driver core: Export the legacy_bus structure for drivers to use.


 drivers/base/platform.c |    3 ++-
 include/linux/device.h  |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)


diff -Nru a/drivers/base/platform.c b/drivers/base/platform.c
--- a/drivers/base/platform.c	Thu Mar 13 16:57:00 2003
+++ b/drivers/base/platform.c	Thu Mar 13 16:57:00 2003
@@ -9,7 +9,7 @@
 #include <linux/module.h>
 #include <linux/init.h>
 
-static struct device legacy_bus = {
+struct device legacy_bus = {
 	.name		= "legacy bus",
 	.bus_id		= "legacy",
 };
@@ -75,5 +75,6 @@
 	return bus_register(&platform_bus_type);
 }
 
+EXPORT_SYMBOL(legacy_bus);
 EXPORT_SYMBOL(platform_device_register);
 EXPORT_SYMBOL(platform_device_unregister);
diff -Nru a/include/linux/device.h b/include/linux/device.h
--- a/include/linux/device.h	Thu Mar 13 16:57:00 2003
+++ b/include/linux/device.h	Thu Mar 13 16:57:00 2003
@@ -366,6 +366,7 @@
 extern void platform_device_unregister(struct platform_device *);
 
 extern struct bus_type platform_bus_type;
+extern struct device legacy_bus;
 
 /* drivers/base/power.c */
 extern int device_suspend(u32 state, u32 level);

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23               ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1111, 2003/03/13 12:16:52-08:00, greg@kroah.com

i2c: i2c-piix4.c: Clean up the ibm dma scan logic

Also export the is_unsafe_smbus variable, which is needed.


 arch/i386/kernel/dmi_scan.c    |    3 +++
 drivers/i2c/busses/i2c-piix4.c |   20 ++------------------
 2 files changed, 5 insertions(+), 18 deletions(-)


diff -Nru a/arch/i386/kernel/dmi_scan.c b/arch/i386/kernel/dmi_scan.c
--- a/arch/i386/kernel/dmi_scan.c	Thu Mar 13 16:57:17 2003
+++ b/arch/i386/kernel/dmi_scan.c	Thu Mar 13 16:57:17 2003
@@ -3,6 +3,7 @@
 #include <linux/kernel.h>
 #include <linux/string.h>
 #include <linux/init.h>
+#include <linux/module.h>
 #include <linux/apm_bios.h>
 #include <linux/slab.h>
 #include <asm/io.h>
@@ -893,3 +894,5 @@
 	if(err = 0)
 		dmi_check_blacklist();
 }
+
+EXPORT_SYMBOL(is_unsafe_smbus);
diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:17 2003
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:17 2003
@@ -28,7 +28,6 @@
    Note: we assume there can only be one device, with one SMBus interface.
 */
 
-#include <linux/version.h>
 #include <linux/module.h>
 #include <linux/config.h>
 #include <linux/pci.h>
@@ -104,31 +103,18 @@
 
 static unsigned short piix4_smba = 0;
 
-#ifdef CONFIG_X86
 /*
  * Get DMI information.
  */
-#if LINUX_VERSION_CODE < KERNEL_VERSION(2,5,34)
-void dmi_scan_mach(void);
-#endif
-
-static int __init ibm_dmi_probe(void)
+static int ibm_dmi_probe(void)
 {
-#if LINUX_VERSION_CODE >= KERNEL_VERSION(2,5,34)
+#ifdef CONFIG_X86
 	extern int is_unsafe_smbus;
 	return is_unsafe_smbus;
 #else
-#define IBM_SIGNATURE		"IBM"
-	dmi_scan_mach();
-	if(dmi_ident[DMI_SYS_VENDOR] = NULL)
-		return 0;
-	if(strncmp(dmi_ident[DMI_SYS_VENDOR], IBM_SIGNATURE,
-	           strlen(IBM_SIGNATURE)) = 0)
-		return 1;
 	return 0;
 #endif
 }
-#endif
 
 static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id)
 {
@@ -141,7 +127,6 @@
 
 	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name);
 
-#ifdef CONFIG_X86
 	if(ibm_dmi_probe()) {
 		printk
 		  (KERN_ERR "i2c-piix4.o: IBM Laptop detected; this module may corrupt\n");
@@ -150,7 +135,6 @@
 		 error_return = -EPERM;
 		 goto END;
 	}
-#endif
 
 /* Determine the address of the SMBus areas */
 	if (force_addr) {

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23                 ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1112, 2003/03/13 12:26:39-08:00, greg@kroah.com

i2c: add i2c sysfs bus support.


 drivers/i2c/i2c-core.c |   33 ++++++++++++++++++++++++++++++---
 include/linux/i2c.h    |    3 +++
 2 files changed, 33 insertions(+), 3 deletions(-)


diff -Nru a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c
--- a/drivers/i2c/i2c-core.c	Thu Mar 13 16:57:09 2003
+++ b/drivers/i2c/i2c-core.c	Thu Mar 13 16:57:09 2003
@@ -598,10 +598,37 @@
 {
 	remove_proc_entry("i2c",proc_bus);
 }
+#else
+static int __init i2cproc_init(void) { return 0; }
+static void __exit i2cproc_cleanup(void) { }
+#endif /* CONFIG_PROC_FS */
 
-module_init(i2cproc_init);
-module_exit(i2cproc_cleanup);
-#endif /* def CONFIG_PROC_FS */
+/* match always succeeds, as we want the probe() to tell if we really accept this match */
+static int i2c_device_match(struct device *dev, struct device_driver *drv)
+{
+	return 1;
+}
+
+struct bus_type i2c_bus_type = {
+	.name =		"i2c",
+	.match =	i2c_device_match,
+};
+
+
+static int __init i2c_init(void)
+{
+	bus_register(&i2c_bus_type);
+	return i2cproc_init();
+}
+
+static void __exit i2c_exit(void)
+{
+	i2cproc_cleanup();
+	bus_unregister(&i2c_bus_type);
+}
+
+module_init(i2c_init);
+module_exit(i2c_exit);
 
 /* ----------------------------------------------------
  * the functional interface to the i2c busses.
diff -Nru a/include/linux/i2c.h b/include/linux/i2c.h
--- a/include/linux/i2c.h	Thu Mar 13 16:57:09 2003
+++ b/include/linux/i2c.h	Thu Mar 13 16:57:09 2003
@@ -34,6 +34,7 @@
 #include <linux/module.h>
 #include <linux/types.h>
 #include <linux/i2c-id.h>
+#include <linux/device.h>	/* for struct device */
 #include <asm/semaphore.h>
 
 /* --- General options ------------------------------------------------	*/
@@ -143,6 +144,8 @@
 	 */
 	int (*command)(struct i2c_client *client,unsigned int cmd, void *arg);
 };
+
+extern struct bus_type i2c_bus_type;
 
 /*
  * i2c_client identifies a single device (i.e. chip) that is connected to an 

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23             ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1110, 2003/03/13 11:59:13-08:00, greg@kroah.com

i2c: get i2c-piix4 driver to actually bind to a PCI device.


 drivers/i2c/busses/i2c-piix4.c |   99 +++++++++++++++++++++--------------------
 1 files changed, 52 insertions(+), 47 deletions(-)


diff -Nru a/drivers/i2c/busses/i2c-piix4.c b/drivers/i2c/busses/i2c-piix4.c
--- a/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:25 2003
+++ b/drivers/i2c/busses/i2c-piix4.c	Thu Mar 13 16:57:25 2003
@@ -49,18 +49,6 @@
 	const char *name;
 };
 
-/* Note: We assume all devices are identical
-         to the Intel PIIX4; we only mention it during detection.   */
-
-static struct sd supported[] = {
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_3, 3, "PIIX4"},
-	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_OSB4, 0, "OSB4"},
-	{PCI_VENDOR_ID_SERVERWORKS, PCI_DEVICE_ID_SERVERWORKS_CSB5, 0, "CSB5"},
-	{PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82443MX_3, 3, "440MX"},
-	{PCI_VENDOR_ID_EFAR, PCI_DEVICE_ID_EFAR_SLC90E66_3, 0, "Victory66"},
-	{0, 0, 0, NULL}
-};
-
 /* PIIX4 SMBus address offsets */
 #define SMBHSTSTS (0 + piix4_smba)
 #define SMBHSLVSTS (1 + piix4_smba)
@@ -142,41 +130,16 @@
 }
 #endif
 
-/* Detect whether a PIIX4 can be found, and initialize it, where necessary.
-   Note the differences between kernels with the old PCI BIOS interface and
-   newer kernels with the real PCI interface. In compat.h some things are
-   defined to make the transition easier. */
-int piix4_setup(void)
+static int piix4_setup(struct pci_dev *PIIX4_dev, const struct pci_device_id *id)
 {
 	int error_return = 0;
 	unsigned char temp;
-	struct sd *num = supported;
-	struct pci_dev *PIIX4_dev = NULL;
 
-	if (pci_present() = 0) {
-		error_return = -ENODEV;
-		goto END;
-	}
+	/* match up the function */
+	if (PCI_FUNC(PIIX4_dev->devfn) != id->driver_data)
+		return -ENODEV;
 
-	/* Look for a supported device/function */
-	do {
-		if((PIIX4_dev = pci_find_device(num->mfr, num->dev,
-					        PIIX4_dev))) {
-			if(PCI_FUNC(PIIX4_dev->devfn) != num->fn)
-				continue;
-			break;
-		}
-		PIIX4_dev = NULL;
-		num++;
-	} while (num->mfr);
-
-	if (PIIX4_dev = NULL) {
-		printk
-		  (KERN_ERR "i2c-piix4.o: Error: Can't detect PIIX4 or compatible device!\n");
-		 error_return = -ENODEV;
-		 goto END;
-	}
-	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", num->name);
+	printk(KERN_INFO "i2c-piix4.o: Found %s device\n", PIIX4_dev->dev.name);
 
 #ifdef CONFIG_X86
 	if(ibm_dmi_probe()) {
@@ -267,14 +230,14 @@
 
 
 /* Internally used pause function */
-void piix4_do_pause(unsigned int amount)
+static void piix4_do_pause(unsigned int amount)
 {
 	current->state = TASK_INTERRUPTIBLE;
 	schedule_timeout(amount);
 }
 
 /* Another internally used function */
-int piix4_transaction(void)
+static int piix4_transaction(void)
 {
 	int temp;
 	int result = 0;
@@ -363,7 +326,7 @@
 }
 
 /* Return -1 on error. */
-s32 piix4_access(struct i2c_adapter * adap, u16 addr,
+static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
 		 unsigned short flags, char read_write,
 		 u8 command, int size, union i2c_smbus_data * data)
 {
@@ -456,7 +419,7 @@
 }
 
 
-u32 piix4_func(struct i2c_adapter *adapter)
+static u32 piix4_func(struct i2c_adapter *adapter)
 {
 	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
 	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
@@ -480,16 +443,58 @@
 
 
 static struct pci_device_id piix4_ids[] __devinitdata = {
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82371AB_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	3
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_SERVERWORKS,
+		.device =	PCI_DEVICE_ID_SERVERWORKS_OSB4,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_SERVERWORKS,
+		.device =	PCI_DEVICE_ID_SERVERWORKS_CSB5,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_INTEL,
+		.device =	PCI_DEVICE_ID_INTEL_82443MX_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	3,
+	},
+	{
+		.vendor =	PCI_VENDOR_ID_EFAR,
+		.device =	PCI_DEVICE_ID_EFAR_SLC90E66_3,
+		.subvendor =	PCI_ANY_ID,
+		.subdevice =	PCI_ANY_ID,
+		.driver_data =	0,
+	},
 	{ 0, }
 };
 
 static int __devinit piix4_probe(struct pci_dev *dev, const struct pci_device_id *id)
 {
+	int retval;
+	
+	retval = piix4_setup(dev, id);
+	if (retval)
+		return retval;
 
 	sprintf(piix4_adapter.name, "SMBus PIIX4 adapter at %04x",
 		piix4_smba);
 
-	i2c_add_adapter(&piix4_adapter);
+	retval = i2c_add_adapter(&piix4_adapter);
+
+	return retval;
 }
 
 static void __devexit piix4_remove(struct pci_dev *dev)

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

* [BK PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23 ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: torvalds; +Cc: linux-kernel, sensors

Hi,

Here's a set of i2c driver changes that start the conversion of the i2c
core and drivers over to the kernel driver model.  Eventually this will
allow all of the sysctl and proc mess to be removed for this subsystem.

These patches add i2c driver bus and i2c adapter driver support to the
driver core.  They also export a needed symbol from the driver core
(which Pat Mochel agreed with doing.) The patches also add three i2c
controllers that have been in the i2c cvs tree for a long time, and are
on a lot of people's machines.

The i2c core needs Christoph's previous patches to work properly, and
with that patch, and these patches, it all works properly on my machines
(tested on 4 different types of i2c controllers.)

Oh, and the i2c development team has given the ok for me to send these
patches to you, and for me to do this work.

Please pull from:  bk://kernel.bkbits.net/gregkh/linux/i2c-2.5


Things left to do after this:
	- clean up #ifdef mess in i2c controllers
	- fix the printk() calls to use proper levels
	- add i2c controller driver core support (present in the patch I
	  previously sent to lkml).
	- add i2c device core support.

thanks,

greg k-h

 arch/i386/kernel/dmi_scan.c      |    3 
 drivers/base/platform.c          |    3 
 drivers/i2c/busses/Kconfig       |   62 +++
 drivers/i2c/busses/Makefile      |    3 
 drivers/i2c/busses/i2c-ali15x3.c |  625 +++++++++++++++++++++++++++++-
 drivers/i2c/busses/i2c-amd756.c  |    3 
 drivers/i2c/busses/i2c-amd8111.c |    5 
 drivers/i2c/busses/i2c-i801.c    |  789 +++++++++++++++++++++++++++++++++++++--
 drivers/i2c/busses/i2c-piix4.c   |  651 ++++++++++++++++++++++++++++----
 drivers/i2c/i2c-core.c           |   46 ++
 include/linux/device.h           |    1 
 include/linux/i2c.h              |    5 
 12 files changed, 2063 insertions(+), 133 deletions(-)
-----

ChangeSet@1.1114, 2003-03-13 16:39:40-08:00, greg@kroah.com
  i2c: add driver model support to i2c adapter drivers

 drivers/i2c/busses/i2c-ali15x3.c |    6 ++++--
 drivers/i2c/busses/i2c-amd756.c  |    3 +++
 drivers/i2c/busses/i2c-amd8111.c |    5 ++++-
 drivers/i2c/busses/i2c-i801.c    |    5 ++++-
 drivers/i2c/busses/i2c-piix4.c   |    3 +++
 drivers/i2c/i2c-core.c           |   13 +++++++++++++
 include/linux/i2c.h              |    2 ++
 7 files changed, 33 insertions(+), 4 deletions(-)
------

ChangeSet@1.1113, 2003-03-13 16:37:27-08:00, greg@kroah.com
  driver core: Export the legacy_bus structure for drivers to use.

 drivers/base/platform.c |    3 ++-
 include/linux/device.h  |    1 +
 2 files changed, 3 insertions(+), 1 deletion(-)
------

ChangeSet@1.1112, 2003-03-13 12:26:39-08:00, greg@kroah.com
  i2c: add i2c sysfs bus support.

 drivers/i2c/i2c-core.c |   33 ++++++++++++++++++++++++++++++---
 include/linux/i2c.h    |    3 +++
 2 files changed, 33 insertions(+), 3 deletions(-)
------

ChangeSet@1.1111, 2003-03-13 12:16:52-08:00, greg@kroah.com
  i2c: i2c-piix4.c: Clean up the ibm dma scan logic
  
  Also export the is_unsafe_smbus variable, which is needed.

 arch/i386/kernel/dmi_scan.c    |    3 +++
 drivers/i2c/busses/i2c-piix4.c |   20 ++------------------
 2 files changed, 5 insertions(+), 18 deletions(-)
------

ChangeSet@1.1110, 2003-03-13 11:59:13-08:00, greg@kroah.com
  i2c: get i2c-piix4 driver to actually bind to a PCI device.

 drivers/i2c/busses/i2c-piix4.c |   99 +++++++++++++++++++++--------------------
 1 files changed, 52 insertions(+), 47 deletions(-)
------

ChangeSet@1.1109, 2003-03-13 11:52:26-08:00, greg@kroah.com
  i2c: add bus driver for Intel PIIX4 devices
  
  This is from the i2c CVS tree.

 drivers/i2c/busses/Kconfig     |   25 +
 drivers/i2c/busses/Makefile    |    1 
 drivers/i2c/busses/i2c-piix4.c |  529 +++++++++++++++++++++++++++++++++++++++++
 3 files changed, 554 insertions(+), 1 deletion(-)
------

ChangeSet@1.1108, 2003-03-13 11:38:03-08:00, greg@kroah.com
  i2c: get i2c-i801 driver to actually bind to a PCI device.

 drivers/i2c/busses/i2c-i801.c |   74 +++++++++++++++++++++---------------------
 1 files changed, 38 insertions(+), 36 deletions(-)
------

ChangeSet@1.1107, 2003-03-13 11:15:15-08:00, greg@kroah.com
  i2c: add bus driver for Intel 801 devices
  
  This is from the i2c CVS tree.

 drivers/i2c/busses/Kconfig    |   23 +
 drivers/i2c/busses/Makefile   |    1 
 drivers/i2c/busses/i2c-i801.c |  710 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 734 insertions(+)
------

ChangeSet@1.1106, 2003-03-13 10:50:41-08:00, greg@kroah.com
  i2c: get i2c-ali15x3 driver to actually bind to a PCI device.

 drivers/i2c/busses/i2c-ali15x3.c |   32 +++++++++-----------------------
 1 files changed, 9 insertions(+), 23 deletions(-)
------

ChangeSet@1.1105, 2003-03-13 10:31:07-08:00, greg@kroah.com
  i2c: add bus driver for ALI15x3 devices
  
  This is from the i2c CVS tree.

 drivers/i2c/busses/Kconfig       |   14 
 drivers/i2c/busses/Makefile      |    1 
 drivers/i2c/busses/i2c-ali15x3.c |  587 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 602 insertions(+)
------

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23       ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1107, 2003/03/13 11:15:15-08:00, greg@kroah.com

i2c: add bus driver for Intel 801 devices

This is from the i2c CVS tree.


 drivers/i2c/busses/Kconfig    |   23 +
 drivers/i2c/busses/Makefile   |    1 
 drivers/i2c/busses/i2c-i801.c |  710 ++++++++++++++++++++++++++++++++++++++++++
 3 files changed, 734 insertions(+)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:50 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 16:57:50 2003
@@ -53,5 +53,28 @@
 	  in the lm_sensors package, which you can download at 
 	  http://www.lm-sensors.nu
 
+config I2C_I801
+	tristate "  Intel 801"
+	depends on I2C && I2C_PROC
+	help
+	  If you say yes to this option, support will be included for the Intel
+	  801 family of mainboard I2C interfaces.  Specifically, the following
+	  versions of the chipset is supported:
+	    82801AA
+	    82801AB
+	    82801BA
+	    82801CA/CAM
+	    82801DB
+
+	  This can also be built as a module which can be inserted and removed 
+	  while the kernel is running.  If you want to compile it as a module,
+	  say M here and read <file:Documentation/modules.txt>.
+
+	  The module will be called i2c-i801.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at 
+	  http://www.lm-sensors.nu
+
 endmenu
 
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:50 2003
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 16:57:50 2003
@@ -5,3 +5,4 @@
 obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
+obj-$(CONFIG_I2C_I801)		+= i2c-i801.o
diff -Nru a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-i801.c	Thu Mar 13 16:57:50 2003
@@ -0,0 +1,710 @@
+/*
+    i801.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
+    Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
+    <mdsxyz123@yahoo.com>
+
+    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.
+*/
+
+/*
+    SUPPORTED DEVICES	PCI ID
+    82801AA		2413           
+    82801AB		2423           
+    82801BA		2443           
+    82801CA/CAM		2483           
+    82801DB		24C3   (HW PEC supported, 32 byte buffer not supported)
+
+    This driver supports several versions of Intel's I/O Controller Hubs (ICH).
+    For SMBus support, they are similar to the PIIX4 and are part
+    of Intel's '810' and other chipsets.
+    See the doc/busses/i2c-i801 file for details.
+    I2C Block Read and Process Call are not supported.
+*/
+
+/* Note: we assume there can only be one I801, with one SMBus interface */
+
+/* #define DEBUG 1 */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
+
+MODULE_LICENSE("GPL");
+
+#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
+#define HAVE_PEC
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS
+#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS	0x2483
+#endif
+
+#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS
+#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS	0x24C3
+#endif
+
+static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
+                          PCI_DEVICE_ID_INTEL_82801AB_3,
+                          PCI_DEVICE_ID_INTEL_82801BA_2,
+			  PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
+			  PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
+                          0 };
+
+/* I801 SMBus address offsets */
+#define SMBHSTSTS (0 + i801_smba)
+#define SMBHSTCNT (2 + i801_smba)
+#define SMBHSTCMD (3 + i801_smba)
+#define SMBHSTADD (4 + i801_smba)
+#define SMBHSTDAT0 (5 + i801_smba)
+#define SMBHSTDAT1 (6 + i801_smba)
+#define SMBBLKDAT (7 + i801_smba)
+#define SMBPEC    (8 + i801_smba)	/* ICH4 only */
+#define SMBAUXSTS (12 + i801_smba)	/* ICH4 only */
+#define SMBAUXCTL (13 + i801_smba)	/* ICH4 only */
+
+/* PCI Address Constants */
+#define SMBBA     0x020
+#define SMBHSTCFG 0x040
+#define SMBREV    0x008
+
+/* Host configuration bits for SMBHSTCFG */
+#define SMBHSTCFG_HST_EN      1
+#define SMBHSTCFG_SMB_SMI_EN  2
+#define SMBHSTCFG_I2C_EN      4
+
+/* Other settings */
+#define MAX_TIMEOUT 100
+#define ENABLE_INT9 0	/* set to 0x01 to enable - untested */
+
+/* I801 command constants */
+#define I801_QUICK          0x00
+#define I801_BYTE           0x04
+#define I801_BYTE_DATA      0x08
+#define I801_WORD_DATA      0x0C
+#define I801_PROC_CALL      0x10	/* later chips only, unimplemented */
+#define I801_BLOCK_DATA     0x14
+#define I801_I2C_BLOCK_DATA 0x18	/* unimplemented */
+#define I801_BLOCK_LAST     0x34
+#define I801_I2C_BLOCK_LAST 0x38	/* unimplemented */
+#define I801_START          0x40
+#define I801_PEC_EN         0x80	/* ICH4 only */
+
+/* insmod parameters */
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the I801 at the given address. VERY DANGEROUS! */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Forcibly enable the I801 at the given address. "
+		 "EXTREMELY DANGEROUS!");
+
+
+
+
+
+static void i801_do_pause(unsigned int amount);
+static int i801_transaction(void);
+static int i801_block_transaction(union i2c_smbus_data *data,
+				  char read_write, int command);
+
+
+
+
+static unsigned short i801_smba = 0;
+static struct pci_dev *I801_dev = NULL;
+static int isich4 = 0;
+
+/* Detect whether a I801 can be found, and initialize it, where necessary.
+   Note the differences between kernels with the old PCI BIOS interface and
+   newer kernels with the real PCI interface. In compat.h some things are
+   defined to make the transition easier. */
+int i801_setup(void)
+{
+	int error_return = 0;
+	int *num = supported;
+	unsigned char temp;
+
+	/* First check whether we can access PCI at all */
+	if (pci_present() = 0) {
+		printk(KERN_WARNING "i2c-i801.o: Error: No PCI-bus found!\n");
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	/* Look for each chip */
+	/* Note: we keep on searching until we have found 'function 3' */
+	I801_dev = NULL;
+	do {
+		if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
+					      *num, I801_dev))) {
+			if(PCI_FUNC(I801_dev->devfn) != 3)
+				continue;
+			break;
+		}
+		num++;
+	} while (*num != 0);
+
+	if (I801_dev = NULL) {
+		printk
+		    (KERN_WARNING "i2c-i801.o: Error: Can't detect I801, function 3!\n");
+		error_return = -ENODEV;
+		goto END;
+	}
+	isich4 = *num = PCI_DEVICE_ID_INTEL_82801DB_SMBUS;
+
+/* Determine the address of the SMBus areas */
+	if (force_addr) {
+		i801_smba = force_addr & 0xfff0;
+	} else {
+		pci_read_config_word(I801_dev, SMBBA, &i801_smba);
+		i801_smba &= 0xfff0;
+		if(i801_smba = 0) {
+			printk(KERN_ERR "i2c-i801.o: SMB base address uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+			return -ENODEV;
+		}
+	}
+
+	if (check_region(i801_smba, (isich4 ? 16 : 8))) {
+		printk
+		    (KERN_ERR "i2c-i801.o: I801_smb region 0x%x already in use!\n",
+		     i801_smba);
+		error_return = -ENODEV;
+		goto END;
+	}
+
+	pci_read_config_byte(I801_dev, SMBHSTCFG, &temp);
+	temp &= ~SMBHSTCFG_I2C_EN;	/* SMBus timing */
+	pci_write_config_byte(I801_dev, SMBHSTCFG, temp);
+/* If force_addr is set, we program the new address here. Just to make
+   sure, we disable the device first. */
+	if (force_addr) {
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp & 0xfe);
+		pci_write_config_word(I801_dev, SMBBA, i801_smba);
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 0x01);
+		printk
+		    (KERN_WARNING "i2c-i801.o: WARNING: I801 SMBus interface set to new "
+		     "address %04x!\n", i801_smba);
+	} else if ((temp & 1) = 0) {
+		pci_write_config_byte(I801_dev, SMBHSTCFG, temp | 1);
+		printk(KERN_WARNING "i2c-i801.o: enabling SMBus device\n");
+	}
+
+	request_region(i801_smba, (isich4 ? 16 : 8), "i801-smbus");
+
+#ifdef DEBUG
+	if (temp & 0x02)
+		printk
+		    (KERN_DEBUG "i2c-i801.o: I801 using Interrupt SMI# for SMBus.\n");
+	else
+		printk
+		    (KERN_DEBUG "i2c-i801.o: I801 using PCI Interrupt for SMBus.\n");
+
+	pci_read_config_byte(I801_dev, SMBREV, &temp);
+	printk(KERN_DEBUG "i2c-i801.o: SMBREV = 0x%X\n", temp);
+	printk(KERN_DEBUG "i2c-i801.o: I801_smba = 0x%X\n", i801_smba);
+#endif				/* DEBUG */
+
+      END:
+	return error_return;
+}
+
+
+void i801_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+int i801_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	/* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
+	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
+		       temp);
+#endif
+		outb_p(temp, SMBHSTSTS);
+		if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Failed! (%02x)\n", temp);
+#endif
+			return -1;
+		} else {
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Successfull!\n");
+#endif
+		}
+	}
+
+	outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+
+	/* We will always wait for a fraction of a second! */
+	do {
+		i801_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
+
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
+		result = -1;
+#endif
+	}
+
+	if (temp & 0x10) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+	if (temp & 0x08) {
+		result = -1;
+		printk
+		    (KERN_ERR "i2c-i801.o: Bus collision! SMBus may be locked until next hard\n"
+		     "reset. (sorry!)\n");
+		/* Clock stops and slave is stuck in mid-transmission */
+	}
+
+	if (temp & 0x04) {
+		result = -1;
+#ifdef DEBUG
+		printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
+#endif
+	}
+
+	if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
+		outb_p(inb(SMBHSTSTS), SMBHSTSTS);
+
+	if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
+#ifdef DEBUG
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Failed reset at end of transaction (%02x)\n",
+		     temp);
+#endif
+	}
+#ifdef DEBUG
+	printk
+	    (KERN_DEBUG "i2c-i801.o: Transaction (post): CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
+	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* All-inclusive block transaction function */
+int i801_block_transaction(union i2c_smbus_data *data, char read_write, 
+                           int command)
+{
+	int i, len;
+	int smbcmd;
+	int temp;
+	int result = 0;
+	int timeout;
+        unsigned char hostc, errmask;
+
+        if (command = I2C_SMBUS_I2C_BLOCK_DATA) {
+                if (read_write = I2C_SMBUS_WRITE) {
+                        /* set I2C_EN bit in configuration register */
+                        pci_read_config_byte(I801_dev, SMBHSTCFG, &hostc);
+                        pci_write_config_byte(I801_dev, SMBHSTCFG, 
+                                              hostc | SMBHSTCFG_I2C_EN);
+                } else {
+                        printk("i2c-i801.o: "
+                               "I2C_SMBUS_I2C_BLOCK_READ not supported!\n");
+                        return -1;
+                }
+        }
+
+	if (read_write = I2C_SMBUS_WRITE) {
+		len = data->block[0];
+		if (len < 1)
+			len = 1;
+		if (len > 32)
+			len = 32;
+		outb_p(len, SMBHSTDAT0);
+		outb_p(data->block[1], SMBBLKDAT);
+	} else {
+		len = 32;	/* max for reads */
+	}
+
+	if(isich4 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
+		/* set 32 byte buffer */
+	}
+
+	for (i = 1; i <= len; i++) {
+		if (i = len && read_write = I2C_SMBUS_READ)
+			smbcmd = I801_BLOCK_LAST;
+		else
+			smbcmd = I801_BLOCK_DATA;
+#if 0 /* now using HW PEC */
+		if(isich4 && command = I2C_SMBUS_BLOCK_DATA_PEC)
+			smbcmd |= I801_PEC_EN;
+#endif
+		outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
+
+#ifdef DEBUG
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Block (pre %d): CNT=%02x, CMD=%02x, ADD=%02x, "
+		     "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT),
+		     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		     inb_p(SMBBLKDAT));
+#endif
+
+		/* Make sure the SMBus host is ready to start transmitting */
+		temp = inb_p(SMBHSTSTS);
+                if (i = 1) {
+                    /* Erronenous conditions before transaction: 
+                     * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
+                    errmask=0x9f; 
+                } else {
+                    /* Erronenous conditions during transaction: 
+                     * Failed, Bus_Err, Dev_Err, Intr */
+                    errmask=0x1e; 
+                }
+		if (temp & errmask) {
+#ifdef DEBUG
+			printk
+			    (KERN_DEBUG "i2c-i801.o: SMBus busy (%02x). Resetting... \n",
+			     temp);
+#endif
+			outb_p(temp, SMBHSTSTS);
+			if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
+				printk
+				    (KERN_ERR "i2c-i801.o: Reset failed! (%02x)\n",
+				     temp);
+				result = -1;
+                                goto END;
+			}
+			if (i != 1) {
+                                result = -1;  /* if die in middle of block transaction, fail */
+                                goto END;
+                        }
+		}
+
+		if (i = 1) {
+#if 0 /* #ifdef HAVE_PEC (now using HW PEC) */
+			if(isich4 && command = I2C_SMBUS_BLOCK_DATA_PEC) {
+				if(read_write = I2C_SMBUS_WRITE)
+					outb_p(data->block[len + 1], SMBPEC);
+			}
+#endif
+			outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
+		}
+
+		/* We will always wait for a fraction of a second! */
+		timeout = 0;
+		do {
+			temp = inb_p(SMBHSTSTS);
+			i801_do_pause(1);
+		}
+		    while ((!(temp & 0x80))
+			   && (timeout++ < MAX_TIMEOUT));
+
+		/* If the SMBus is still busy, we give up */
+		if (timeout >= MAX_TIMEOUT) {
+			result = -1;
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: SMBus Timeout!\n");
+#endif
+		}
+
+		if (temp & 0x10) {
+			result = -1;
+#ifdef DEBUG
+			printk
+			    (KERN_DEBUG "i2c-i801.o: Error: Failed bus transaction\n");
+#endif
+		} else if (temp & 0x08) {
+			result = -1;
+			printk(KERN_ERR "i2c-i801.o: Bus collision!\n");
+		} else if (temp & 0x04) {
+			result = -1;
+#ifdef DEBUG
+			printk(KERN_DEBUG "i2c-i801.o: Error: no response!\n");
+#endif
+		}
+
+		if (i = 1 && read_write = I2C_SMBUS_READ) {
+			len = inb_p(SMBHSTDAT0);
+			if (len < 1)
+				len = 1;
+			if (len > 32)
+				len = 32;
+			data->block[0] = len;
+		}
+
+                /* Retrieve/store value in SMBBLKDAT */
+		if (read_write = I2C_SMBUS_READ)
+			data->block[i] = inb_p(SMBBLKDAT);
+		if (read_write = I2C_SMBUS_WRITE && i+1 <= len)
+			outb_p(data->block[i+1], SMBBLKDAT);
+		if ((temp & 0x9e) != 0x00)
+			outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */
+
+#ifdef DEBUG
+		if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
+			printk
+			    (KERN_DEBUG "i2c-i801.o: Bad status (%02x) at end of transaction\n",
+			     temp);
+		}
+		printk
+		    (KERN_DEBUG "i2c-i801.o: Block (post %d): CNT=%02x, CMD=%02x, ADD=%02x, "
+		     "DAT0=%02x, BLKDAT=%02x\n", i, inb_p(SMBHSTCNT),
+		     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+		     inb_p(SMBBLKDAT));
+#endif
+
+		if (result < 0)
+			goto END;
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && command = I2C_SMBUS_BLOCK_DATA_PEC) {
+		/* wait for INTR bit as advised by Intel */
+		timeout = 0;
+		do {
+			temp = inb_p(SMBHSTSTS);
+			i801_do_pause(1);
+		} while ((!(temp & 0x02))
+			   && (timeout++ < MAX_TIMEOUT));
+
+		if (timeout >= MAX_TIMEOUT) {
+			printk(KERN_DEBUG "i2c-i801.o: PEC Timeout!\n");
+		}
+#if 0 /* now using HW PEC */
+		if(read_write = I2C_SMBUS_READ) {
+			data->block[len + 1] = inb_p(SMBPEC);
+		}
+#endif
+		outb_p(temp, SMBHSTSTS); 
+	}
+#endif
+        result = 0;
+END:
+        if (command = I2C_SMBUS_I2C_BLOCK_DATA) {
+                /* restore saved configuration register value */
+		pci_write_config_byte(I801_dev, SMBHSTCFG, hostc);
+        }
+	return result;
+}
+
+/* Return -1 on error. */
+s32 i801_access(struct i2c_adapter * adap, u16 addr, unsigned short flags,
+		char read_write, u8 command, int size,
+		union i2c_smbus_data * data)
+{
+	int hwpec = 0;
+	int block = 0;
+	int ret, xact = 0;
+
+#ifdef HAVE_PEC
+	if(isich4)
+		hwpec = (flags & I2C_CLIENT_PEC) != 0;
+#endif
+
+	switch (size) {
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		xact = I801_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write = I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		xact = I801_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		xact = I801_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		xact = I801_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+	case I2C_SMBUS_I2C_BLOCK_DATA:
+#ifdef HAVE_PEC
+	case I2C_SMBUS_BLOCK_DATA_PEC:
+		if(hwpec && size = I2C_SMBUS_BLOCK_DATA)
+			size = I2C_SMBUS_BLOCK_DATA_PEC;
+#endif
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		block = 1;
+		break;
+	case I2C_SMBUS_PROC_CALL:
+	default:
+		printk(KERN_ERR "i2c-i801.o: Unsupported transaction %d\n", size);
+		return -1;
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && hwpec) {
+		if(size != I2C_SMBUS_QUICK &&
+		   size != I2C_SMBUS_I2C_BLOCK_DATA)
+			outb_p(1, SMBAUXCTL);	/* enable HW PEC */
+	}
+#endif
+	if(block)
+		ret = i801_block_transaction(data, read_write, size);
+	else {
+		outb_p(xact | ENABLE_INT9, SMBHSTCNT);
+		ret = i801_transaction();
+	}
+
+#ifdef HAVE_PEC
+	if(isich4 && hwpec) {
+		if(size != I2C_SMBUS_QUICK &&
+		   size != I2C_SMBUS_I2C_BLOCK_DATA)
+			outb_p(0, SMBAUXCTL);
+	}
+#endif
+
+	if(block)
+		return ret;
+	if(ret)
+		return -1;
+	if ((read_write = I2C_SMBUS_WRITE) || (xact = I801_QUICK))
+		return 0;
+
+	switch (xact & 0x7f) {
+	case I801_BYTE:	/* Result put in SMBHSTDAT0 */
+	case I801_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case I801_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	}
+	return 0;
+}
+
+
+u32 i801_func(struct i2c_adapter *adapter)
+{
+	return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+	    I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_WRITE_I2C_BLOCK
+#ifdef HAVE_PEC
+	     | (isich4 ? I2C_FUNC_SMBUS_BLOCK_DATA_PEC |
+	                 I2C_FUNC_SMBUS_HWPEC_CALC
+	               : 0)
+#endif
+	    ;
+}
+
+static struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= i801_access,
+	.functionality	= i801_func,
+};
+
+static struct i2c_adapter i801_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_I801,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id i801_ids[] __devinitdata = {
+	{ 0, }
+};
+
+static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+
+	if (i801_setup()) {
+		printk
+		    (KERN_WARNING "i2c-i801.o: I801 not detected, module not inserted.\n");
+		return -ENODEV;
+	}
+
+	sprintf(i801_adapter.name, "SMBus I801 adapter at %04x",
+		i801_smba);
+	i2c_add_adapter(&i801_adapter);
+}
+
+static void __devexit i801_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&i801_adapter);
+}
+
+static struct pci_driver i801_driver = {
+	.name		= "i801 smbus",
+	.id_table	= i801_ids,
+	.probe		= i801_probe,
+	.remove		= __devexit_p(i801_remove),
+};
+
+static int __init i2c_i801_init(void)
+{
+	printk(KERN_INFO "i2c-i801.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&i801_driver);
+}
+
+
+static void __exit i2c_i801_exit(void)
+{
+	pci_unregister_driver(&i801_driver);
+	release_region(i801_smba, (isich4 ? 16 : 8));
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("I801 SMBus driver");
+
+module_init(i2c_i801_init);
+module_exit(i2c_i801_exit);

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23   ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: linux-kernel, sensors

ChangeSet 1.1105, 2003/03/13 10:31:07-08:00, greg@kroah.com

i2c: add bus driver for ALI15x3 devices

This is from the i2c CVS tree.


 drivers/i2c/busses/Kconfig       |   14 
 drivers/i2c/busses/Makefile      |    1 
 drivers/i2c/busses/i2c-ali15x3.c |  587 +++++++++++++++++++++++++++++++++++++++
 3 files changed, 602 insertions(+)


diff -Nru a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
--- a/drivers/i2c/busses/Kconfig	Thu Mar 13 16:58:06 2003
+++ b/drivers/i2c/busses/Kconfig	Thu Mar 13 16:58:06 2003
@@ -5,6 +5,20 @@
 
 menu "I2C Hardware Sensors Mainboard support"
 
+config I2C_ALI15X3
+	tristate "  ALI 15x3"
+	depends on I2C && I2C_PROC && PCI && EXPERIMENTAL
+	help
+	  If you say yes to this option, support will be included for the
+	  Acer Labs Inc. (ALI) M1514 and M1543 motherboard I2C interfaces.
+
+	  This can also be built as a module.  If so, the module will be
+	  called i2c-ali15x3.
+
+	  You will also need the latest user-space utilties: you can find them
+	  in the lm_sensors package, which you can download at
+	  http://www.lm-sensors.nu
+
 config I2C_AMD756
 	tristate "  AMD 756/766"
 	depends on I2C && I2C_PROC
diff -Nru a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
--- a/drivers/i2c/busses/Makefile	Thu Mar 13 16:58:06 2003
+++ b/drivers/i2c/busses/Makefile	Thu Mar 13 16:58:06 2003
@@ -2,5 +2,6 @@
 # Makefile for the kernel hardware sensors bus drivers.
 #
 
+obj-$(CONFIG_I2C_ALI15X3)	+= i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)	+= i2c-amd756.o
 obj-$(CONFIG_I2C_AMD8111)	+= i2c-amd8111.o
diff -Nru a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
--- /dev/null	Wed Dec 31 16:00:00 1969
+++ b/drivers/i2c/busses/i2c-ali15x3.c	Thu Mar 13 16:58:06 2003
@@ -0,0 +1,587 @@
+/*
+    ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
+              monitoring
+    Copyright (c) 1999  Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com> and
+    Mark D. Studebaker <mdsxyz123@yahoo.com>
+
+    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.
+*/
+
+/*
+    This is the driver for the SMB Host controller on
+    Acer Labs Inc. (ALI) M1541 and M1543C South Bridges.
+
+    The M1543C is a South bridge for desktop systems.
+    The M1533 is a South bridge for portable systems.
+    They are part of the following ALI chipsets:
+       "Aladdin Pro 2": Includes the M1621 Slot 1 North bridge
+       with AGP and 100MHz CPU Front Side bus
+       "Aladdin V": Includes the M1541 Socket 7 North bridge
+       with AGP and 100MHz CPU Front Side bus
+       "Aladdin IV": Includes the M1541 Socket 7 North bridge
+       with host bus up to 83.3 MHz.
+    For an overview of these chips see http://www.acerlabs.com
+
+    The M1533/M1543C devices appear as FOUR separate devices
+    on the PCI bus. An output of lspci will show something similar
+    to the following:
+
+	00:02.0 USB Controller: Acer Laboratories Inc. M5237
+	00:03.0 Bridge: Acer Laboratories Inc. M7101
+	00:07.0 ISA bridge: Acer Laboratories Inc. M1533
+	00:0f.0 IDE interface: Acer Laboratories Inc. M5229
+
+    The SMB controller is part of the 7101 device, which is an
+    ACPI-compliant Power Management Unit (PMU).
+
+    The whole 7101 device has to be enabled for the SMB to work.
+    You can't just enable the SMB alone.
+    The SMB and the ACPI have separate I/O spaces.
+    We make sure that the SMB is enabled. We leave the ACPI alone.
+
+    This driver controls the SMB Host only.
+    The SMB Slave controller on the M15X3 is not enabled.
+
+    This driver does not use interrupts.
+*/
+
+/* Note: we assume there can only be one ALI15X3, with one SMBus interface */
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/stddef.h>
+#include <linux/sched.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <asm/io.h>
+
+/* ALI15X3 SMBus address offsets */
+#define SMBHSTSTS (0 + ali15x3_smba)
+#define SMBHSTCNT (1 + ali15x3_smba)
+#define SMBHSTSTART (2 + ali15x3_smba)
+#define SMBHSTCMD (7 + ali15x3_smba)
+#define SMBHSTADD (3 + ali15x3_smba)
+#define SMBHSTDAT0 (4 + ali15x3_smba)
+#define SMBHSTDAT1 (5 + ali15x3_smba)
+#define SMBBLKDAT (6 + ali15x3_smba)
+
+/* PCI Address Constants */
+#define SMBCOM    0x004
+#define SMBBA     0x014
+#define SMBATPC   0x05B		/* used to unlock xxxBA registers */
+#define SMBHSTCFG 0x0E0
+#define SMBSLVC   0x0E1
+#define SMBCLK    0x0E2
+#define SMBREV    0x008
+
+/* Other settings */
+#define MAX_TIMEOUT 200		/* times 1/100 sec */
+#define ALI15X3_SMB_IOSIZE 32
+
+/* this is what the Award 1004 BIOS sets them to on a ASUS P5A MB.
+   We don't use these here. If the bases aren't set to some value we
+   tell user to upgrade BIOS and we fail.
+*/
+#define ALI15X3_SMB_DEFAULTBASE 0xE800
+
+/* ALI15X3 address lock bits */
+#define ALI15X3_LOCK	0x06
+
+/* ALI15X3 command constants */
+#define ALI15X3_ABORT      0x02
+#define ALI15X3_T_OUT      0x04
+#define ALI15X3_QUICK      0x00
+#define ALI15X3_BYTE       0x10
+#define ALI15X3_BYTE_DATA  0x20
+#define ALI15X3_WORD_DATA  0x30
+#define ALI15X3_BLOCK_DATA 0x40
+#define ALI15X3_BLOCK_CLR  0x80
+
+/* ALI15X3 status register bits */
+#define ALI15X3_STS_IDLE	0x04
+#define ALI15X3_STS_BUSY	0x08
+#define ALI15X3_STS_DONE	0x10
+#define ALI15X3_STS_DEV		0x20	/* device error */
+#define ALI15X3_STS_COLL	0x40	/* collision or no response */
+#define ALI15X3_STS_TERM	0x80	/* terminated by abort */
+#define ALI15X3_STS_ERR		0xE0	/* all the bad error bits */
+
+
+/* If force_addr is set to anything different from 0, we forcibly enable
+   the device at the given address. */
+static int force_addr = 0;
+MODULE_PARM(force_addr, "i");
+MODULE_PARM_DESC(force_addr,
+		 "Initialize the base address of the i2c controller");
+
+
+static void ali15x3_do_pause(unsigned int amount);
+static int ali15x3_transaction(void);
+
+static unsigned short ali15x3_smba = 0;
+
+/* Detect whether a ALI15X3 can be found, and initialize it, where necessary.
+   Note the differences between kernels with the old PCI BIOS interface and
+   newer kernels with the real PCI interface. In compat.h some things are
+   defined to make the transition easier. */
+int ali15x3_setup(void)
+{
+	u16 a;
+	unsigned char temp;
+
+	struct pci_dev *ALI15X3_dev;
+
+	/* First check whether we can access PCI at all */
+	if (pci_present() = 0) {
+		printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
+		return -ENODEV;
+	}
+
+	/* Look for the ALI15X3, M7101 device */
+	ALI15X3_dev = NULL;
+	ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
+				      PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
+	if (ALI15X3_dev = NULL) {
+		printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
+		return -ENODEV;
+	}
+
+/* Check the following things:
+	- SMB I/O address is initialized
+	- Device is enabled
+	- We can use the addresses
+*/
+
+/* Unlock the register.
+   The data sheet says that the address registers are read-only
+   if the lock bits are 1, but in fact the address registers
+   are zero unless you clear the lock bits.
+*/
+	pci_read_config_byte(ALI15X3_dev, SMBATPC, &temp);
+	if (temp & ALI15X3_LOCK) {
+		temp &= ~ALI15X3_LOCK;
+		pci_write_config_byte(ALI15X3_dev, SMBATPC, temp);
+	}
+
+/* Determine the address of the SMBus area */
+	pci_read_config_word(ALI15X3_dev, SMBBA, &ali15x3_smba);
+	ali15x3_smba &= (0xffff & ~(ALI15X3_SMB_IOSIZE - 1));
+	if (ali15x3_smba = 0 && force_addr = 0) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3_smb region uninitialized - upgrade BIOS or use force_addr=0xaddr\n");
+		return -ENODEV;
+	}
+
+	if(force_addr)
+		ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
+
+	if (check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE)) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3_smb region 0x%x already in use!\n",
+		     ali15x3_smba);
+		return -ENODEV;
+	}
+
+	if(force_addr) {
+		printk("i2c-ali15x3.o: forcing ISA address 0x%04X\n", ali15x3_smba);
+		if (PCIBIOS_SUCCESSFUL !+		    pci_write_config_word(ALI15X3_dev, SMBBA, ali15x3_smba))
+			return -ENODEV;
+		if (PCIBIOS_SUCCESSFUL !+		    pci_read_config_word(ALI15X3_dev, SMBBA, &a))
+			return -ENODEV;
+		if ((a & ~(ALI15X3_SMB_IOSIZE - 1)) != ali15x3_smba) {
+			/* make sure it works */
+			printk("i2c-ali15x3.o: force address failed - not supported?\n");
+			return -ENODEV;
+		}
+	}
+/* check if whole device is enabled */
+	pci_read_config_byte(ALI15X3_dev, SMBCOM, &temp);
+	if ((temp & 1) = 0) {
+		printk("i2c-ali15x3: enabling SMBus device\n");
+		pci_write_config_byte(ALI15X3_dev, SMBCOM, temp | 0x01);
+	}
+
+/* Is SMB Host controller enabled? */
+	pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
+	if ((temp & 1) = 0) {
+		printk("i2c-ali15x3: enabling SMBus controller\n");
+		pci_write_config_byte(ALI15X3_dev, SMBHSTCFG, temp | 0x01);
+	}
+
+/* set SMB clock to 74KHz as recommended in data sheet */
+	pci_write_config_byte(ALI15X3_dev, SMBCLK, 0x20);
+
+	/* Everything is happy, let's grab the memory and set things up. */
+	request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE, "ali15x3-smb");
+
+#ifdef DEBUG
+/*
+  The interrupt routing for SMB is set up in register 0x77 in the
+  1533 ISA Bridge device, NOT in the 7101 device.
+  Don't bother with finding the 1533 device and reading the register.
+  if ((....... & 0x0F) = 1)
+     printk("i2c-ali15x3.o: ALI15X3 using Interrupt 9 for SMBus.\n");
+*/
+	pci_read_config_byte(ALI15X3_dev, SMBREV, &temp);
+	printk("i2c-ali15x3.o: SMBREV = 0x%X\n", temp);
+	printk("i2c-ali15x3.o: ALI15X3_smba = 0x%X\n", ali15x3_smba);
+#endif				/* DEBUG */
+
+	return 0;
+}
+
+
+/* Internally used pause function */
+void ali15x3_do_pause(unsigned int amount)
+{
+	current->state = TASK_INTERRUPTIBLE;
+	schedule_timeout(amount);
+}
+
+/* Another internally used function */
+int ali15x3_transaction(void)
+{
+	int temp;
+	int result = 0;
+	int timeout = 0;
+
+#ifdef DEBUG
+	printk
+	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
+	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+	     inb_p(SMBHSTDAT1));
+#endif
+
+	/* get status */
+	temp = inb_p(SMBHSTSTS);
+
+	/* Make sure the SMBus host is ready to start transmitting */
+	/* Check the busy bit first */
+	if (temp & ALI15X3_STS_BUSY) {
+/*
+   If the host controller is still busy, it may have timed out in the previous transaction,
+   resulting in a "SMBus Timeout" printk.
+   I've tried the following to reset a stuck busy bit.
+	1. Reset the controller with an ABORT command.
+	   (this doesn't seem to clear the controller if an external device is hung)
+	2. Reset the controller and the other SMBus devices with a T_OUT command.
+	   (this clears the host busy bit if an external device is hung,
+	   but it comes back upon a new access to a device)
+	3. Disable and reenable the controller in SMBHSTCFG
+   Worst case, nothing seems to work except power reset.
+*/
+/* Abort - reset the host controller */
+/*
+#ifdef DEBUG
+    printk("i2c-ali15x3.o: Resetting host controller to clear busy condition\n",temp);
+#endif
+    outb_p(ALI15X3_ABORT, SMBHSTCNT);
+    temp = inb_p(SMBHSTSTS);
+    if (temp & ALI15X3_STS_BUSY) {
+*/
+
+/*
+   Try resetting entire SMB bus, including other devices -
+   This may not work either - it clears the BUSY bit but
+   then the BUSY bit may come back on when you try and use the chip again.
+   If that's the case you are stuck.
+*/
+		printk
+		    ("i2c-ali15x3.o: Resetting entire SMB Bus to clear busy condition (%02x)\n",
+		     temp);
+		outb_p(ALI15X3_T_OUT, SMBHSTCNT);
+		temp = inb_p(SMBHSTSTS);
+	}
+/*
+  }
+*/
+
+	/* now check the error bits and the busy bit */
+	if (temp & (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
+		/* do a clear-on-write */
+		outb_p(0xFF, SMBHSTSTS);
+		if ((temp = inb_p(SMBHSTSTS)) &
+		    (ALI15X3_STS_ERR | ALI15X3_STS_BUSY)) {
+			/* this is probably going to be correctable only by a power reset
+			   as one of the bits now appears to be stuck */
+			/* This may be a bus or device with electrical problems. */
+			printk
+			    ("i2c-ali15x3.o: SMBus reset failed! (0x%02x) - controller or device on bus is probably hung\n",
+			     temp);
+			return -1;
+		}
+	} else {
+		/* check and clear done bit */
+		if (temp & ALI15X3_STS_DONE) {
+			outb_p(temp, SMBHSTSTS);
+		}
+	}
+
+	/* start the transaction by writing anything to the start register */
+	outb_p(0xFF, SMBHSTSTART);
+
+	/* We will always wait for a fraction of a second! */
+	timeout = 0;
+	do {
+		ali15x3_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	} while ((!(temp & (ALI15X3_STS_ERR | ALI15X3_STS_DONE)))
+		 && (timeout++ < MAX_TIMEOUT));
+
+	/* If the SMBus is still busy, we give up */
+	if (timeout >= MAX_TIMEOUT) {
+		result = -1;
+		printk("i2c-ali15x3.o: SMBus Timeout!\n");
+	}
+
+	if (temp & ALI15X3_STS_TERM) {
+		result = -1;
+#ifdef DEBUG
+		printk("i2c-ali15x3.o: Error: Failed bus transaction\n");
+#endif
+	}
+
+/*
+  Unfortunately the ALI SMB controller maps "no response" and "bus collision"
+  into a single bit. No reponse is the usual case so don't
+  do a printk.
+  This means that bus collisions go unreported.
+*/
+	if (temp & ALI15X3_STS_COLL) {
+		result = -1;
+#ifdef DEBUG
+		printk
+		    ("i2c-ali15x3.o: Error: no response or bus collision ADD=%02x\n",
+		     inb_p(SMBHSTADD));
+#endif
+	}
+
+/* haven't ever seen this */
+	if (temp & ALI15X3_STS_DEV) {
+		result = -1;
+		printk("i2c-ali15x3.o: Error: device error\n");
+	}
+#ifdef DEBUG
+	printk
+	    ("i2c-ali15x3.o: Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, "
+	     "DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
+	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
+	     inb_p(SMBHSTDAT1));
+#endif
+	return result;
+}
+
+/* Return -1 on error. */
+s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
+		   unsigned short flags, char read_write, u8 command,
+		   int size, union i2c_smbus_data * data)
+{
+	int i, len;
+	int temp;
+	int timeout;
+
+/* clear all the bits (clear-on-write) */
+	outb_p(0xFF, SMBHSTSTS);
+/* make sure SMBus is idle */
+	temp = inb_p(SMBHSTSTS);
+	for (timeout = 0;
+	     (timeout < MAX_TIMEOUT) && !(temp & ALI15X3_STS_IDLE);
+	     timeout++) {
+		ali15x3_do_pause(1);
+		temp = inb_p(SMBHSTSTS);
+	}
+	if (timeout >= MAX_TIMEOUT) {
+		printk("i2c-ali15x3.o: Idle wait Timeout! STS=0x%02x\n",
+		       temp);
+	}
+
+	switch (size) {
+	case I2C_SMBUS_PROC_CALL:
+		printk
+		    ("i2c-ali15x3.o: I2C_SMBUS_PROC_CALL not supported!\n");
+		return -1;
+	case I2C_SMBUS_QUICK:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		size = ALI15X3_QUICK;
+		break;
+	case I2C_SMBUS_BYTE:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		if (read_write = I2C_SMBUS_WRITE)
+			outb_p(command, SMBHSTCMD);
+		size = ALI15X3_BYTE;
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE)
+			outb_p(data->byte, SMBHSTDAT0);
+		size = ALI15X3_BYTE_DATA;
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE) {
+			outb_p(data->word & 0xff, SMBHSTDAT0);
+			outb_p((data->word & 0xff00) >> 8, SMBHSTDAT1);
+		}
+		size = ALI15X3_WORD_DATA;
+		break;
+	case I2C_SMBUS_BLOCK_DATA:
+		outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+		       SMBHSTADD);
+		outb_p(command, SMBHSTCMD);
+		if (read_write = I2C_SMBUS_WRITE) {
+			len = data->block[0];
+			if (len < 0) {
+				len = 0;
+				data->block[0] = len;
+			}
+			if (len > 32) {
+				len = 32;
+				data->block[0] = len;
+			}
+			outb_p(len, SMBHSTDAT0);
+			outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);	/* Reset SMBBLKDAT */
+			for (i = 1; i <= len; i++)
+				outb_p(data->block[i], SMBBLKDAT);
+		}
+		size = ALI15X3_BLOCK_DATA;
+		break;
+	}
+
+	outb_p(size, SMBHSTCNT);	/* output command */
+
+	if (ali15x3_transaction())	/* Error in transaction */
+		return -1;
+
+	if ((read_write = I2C_SMBUS_WRITE) || (size = ALI15X3_QUICK))
+		return 0;
+
+
+	switch (size) {
+	case ALI15X3_BYTE:	/* Result put in SMBHSTDAT0 */
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case ALI15X3_BYTE_DATA:
+		data->byte = inb_p(SMBHSTDAT0);
+		break;
+	case ALI15X3_WORD_DATA:
+		data->word = inb_p(SMBHSTDAT0) + (inb_p(SMBHSTDAT1) << 8);
+		break;
+	case ALI15X3_BLOCK_DATA:
+		len = inb_p(SMBHSTDAT0);
+		if (len > 32)
+			len = 32;
+		data->block[0] = len;
+		outb_p(inb_p(SMBHSTCNT) | ALI15X3_BLOCK_CLR, SMBHSTCNT);	/* Reset SMBBLKDAT */
+		for (i = 1; i <= data->block[0]; i++) {
+			data->block[i] = inb_p(SMBBLKDAT);
+#ifdef DEBUG
+			printk
+			    ("i2c-ali15x3.o: Blk: len=%d, i=%d, data=%02x\n",
+			     len, i, data->block[i]);
+#endif	/* DEBUG */
+		}
+		break;
+	}
+	return 0;
+}
+
+
+u32 ali15x3_func(struct i2c_adapter *adapter)
+{
+	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 struct i2c_algorithm smbus_algorithm = {
+	.name		= "Non-I2C SMBus adapter",
+	.id		= I2C_ALGO_SMBUS,
+	.smbus_xfer	= ali15x3_access,
+	.functionality	= ali15x3_func,
+};
+
+static struct i2c_adapter ali15x3_adapter = {
+	.owner		= THIS_MODULE,
+	.name		= "unset",
+	.id		= I2C_ALGO_SMBUS | I2C_HW_SMBUS_ALI15X3,
+	.algo		= &smbus_algorithm,
+};
+
+
+
+static struct pci_device_id ali15x3_ids[] __devinitdata = {
+	{ 0, }
+};
+
+static int __devinit ali15x3_probe(struct pci_dev *dev, const struct pci_device_id *id)
+{
+	if (ali15x3_setup()) {
+		printk
+		    ("i2c-ali15x3.o: ALI15X3 not detected, module not inserted.\n");
+
+		return -ENODEV;
+	}
+
+	sprintf(ali15x3_adapter.name, "SMBus ALI15X3 adapter at %04x",
+		ali15x3_smba);
+	i2c_add_adapter(&ali15x3_adapter);
+}
+
+static void __devexit ali15x3_remove(struct pci_dev *dev)
+{
+	i2c_del_adapter(&ali15x3_adapter);
+}
+
+static struct pci_driver ali15x3_driver = {
+	.name		= "ali15x3 smbus",
+	.id_table	= ali15x3_ids,
+	.probe		= ali15x3_probe,
+	.remove		= __devexit_p(ali15x3_remove),
+};
+
+static int __init i2c_ali15x3_init(void)
+{
+	printk("i2c-ali15x3.o version %s (%s)\n", I2C_VERSION, I2C_DATE);
+	return pci_module_init(&ali15x3_driver);
+}
+
+
+static void __exit i2c_ali15x3_exit(void)
+{
+	pci_unregister_driver(&ali15x3_driver);
+	release_region(ali15x3_smba, ALI15X3_SMB_IOSIZE);
+}
+
+
+
+MODULE_AUTHOR
+    ("Frodo Looijaard <frodol@dds.nl>, Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker <mdsxyz123@yahoo.com>");
+MODULE_DESCRIPTION("ALI15X3 SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_ali15x3_init);
+module_exit(i2c_ali15x3_exit);

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23     ` Christoph Hellwig
  0 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> +/* Detect whether a ALI15X3 can be found, and initialize it, where necessary.
> +   Note the differences between kernels with the old PCI BIOS interface and
> +   newer kernels with the real PCI interface. In compat.h some things are
> +   defined to make the transition easier. */

This comment seems a bit outdated..

> +int ali15x3_setup(void)

Should be static like everything in this file (and merged into
ali15x3_probe anyway).

> +{
> +	u16 a;
> +	unsigned char temp;
> +
> +	struct pci_dev *ALI15X3_dev;
> +
> +	/* First check whether we can access PCI at all */
> +	if (pci_present() = 0) {
> +		printk("i2c-ali15x3.o: Error: No PCI-bus found!\n");
> +		return -ENODEV;
> +	}

You're calling this from pci_driver->probe, so you will never get
here without PCI hardware.

> +	/* Look for the ALI15X3, M7101 device */
> +	ALI15X3_dev = NULL;
> +	ALI15X3_dev = pci_find_device(PCI_VENDOR_ID_AL,
> +				      PCI_DEVICE_ID_AL_M7101, ALI15X3_dev);
> +	if (ALI15X3_dev = NULL) {
> +		printk("i2c-ali15x3.o: Error: Can't detect ali15x3!\n");
> +		return -ENODEV;
> +	}

Calling pci_find_device in ->probe looks buggy to me.  What are you
trying to do?

> +/* Is SMB Host controller enabled? */
> +	pci_read_config_byte(ALI15X3_dev, SMBHSTCFG, &temp);
> +	if ((temp & 1) = 0) {

What about proper indentation for the comments?

> +/* Internally used pause function */
> +void ali15x3_do_pause(unsigned int amount)
> +{
> +	current->state = TASK_INTERRUPTIBLE;
> +	schedule_timeout(amount);
> +}

I think this should be moved to linux/kernel.h as delay() - I've seen
it duplicated in so much code (including XFS)

> +#ifdef DEBUG
> +	printk
> +	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
> +	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
> +	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
> +	     inb_p(SMBHSTDAT1));
> +#endif

use pr_debug() here.

> +static struct pci_device_id ali15x3_ids[] __devinitdata = {
> +	{ 0, }
> +};

Umm?

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23       ` Christoph Hellwig
  0 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com
> 
> i2c: get i2c-ali15x3 driver to actually bind to a PCI device.

OOPS, should take a look at all patches first before complaining :)

>  static struct pci_device_id ali15x3_ids[] __devinitdata = {
> +	{
> +	.vendor =	PCI_VENDOR_ID_AL,
> +	.device =	PCI_DEVICE_ID_AL_M7101,
> +	.subvendor =	PCI_ANY_ID,
> +	.subdevice =	PCI_ANY_ID,
> +	},

The indentation looks a bit b0rked..

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23         ` Christoph Hellwig
  0 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> +#include <linux/i2c.h>
> +#include <asm/io.h>
> +
> +MODULE_LICENSE("GPL");

This should be at the bottom of the file with the other MODULE_* stuff

> +#ifdef I2C_FUNC_SMBUS_BLOCK_DATA_PEC
> +#define HAVE_PEC
> +#endif

Needs more explanation.

> +
> +#ifndef PCI_DEVICE_ID_INTEL_82801CA_SMBUS
> +#define PCI_DEVICE_ID_INTEL_82801CA_SMBUS	0x2483
> +#endif
> +
> +#ifndef PCI_DEVICE_ID_INTEL_82801DB_SMBUS
> +#define PCI_DEVICE_ID_INTEL_82801DB_SMBUS	0x24C3
> +#endif

Should go to pci_ids.h

> +
> +static int supported[] = {PCI_DEVICE_ID_INTEL_82801AA_3,
> +                          PCI_DEVICE_ID_INTEL_82801AB_3,
> +                          PCI_DEVICE_ID_INTEL_82801BA_2,
> +			  PCI_DEVICE_ID_INTEL_82801CA_SMBUS,
> +			  PCI_DEVICE_ID_INTEL_82801DB_SMBUS,
> +                          0 };

Shouldn't be required with new-style pci probing.

> +static int force_addr = 0;
> +MODULE_PARM(force_addr, "i");
> +MODULE_PARM_DESC(force_addr,
> +		 "Forcibly enable the I801 at the given address. "
> +		 "EXTREMELY DANGEROUS!");

What about using Rusty's new module parameter stuff?

> +static unsigned short i801_smba = 0;
> +static struct pci_dev *I801_dev = NULL;
> +static int isich4 = 0;

This is in .bss..

> +/* Detect whether a I801 can be found, and initialize it, where necessary.
> +   Note the differences between kernels with the old PCI BIOS interface and
> +   newer kernels with the real PCI interface. In compat.h some things are
> +   defined to make the transition easier. */
> +int i801_setup(void)

Merge with caller, comment is b0rked.

> +{
> +	int error_return = 0;
> +	int *num = supported;
> +	unsigned char temp;
> +
> +	/* First check whether we can access PCI at all */
> +	if (pci_present() = 0) {
> +		printk(KERN_WARNING "i2c-i801.o: Error: No PCI-bus found!\n");
> +		error_return = -ENODEV;
> +		goto END;
> +	}

END is a bad name for a label.  

> +	/* Look for each chip */
> +	/* Note: we keep on searching until we have found 'function 3' */
> +	I801_dev = NULL;
> +	do {
> +		if((I801_dev = pci_find_device(PCI_VENDOR_ID_INTEL,
> +					      *num, I801_dev))) {
> +			if(PCI_FUNC(I801_dev->devfn) != 3)
> +				continue;
> +			break;
> +		}
> +		num++;
> +	} while (*num != 0);

You already changed it to new-style pci probing in the next patch, didn't
you?

> +	if (check_region(i801_smba, (isich4 ? 16 : 8))) {

no way!

> +int i801_transaction(void)

static..

> +	int temp;
> +	int result = 0;
> +	int timeout = 0;
> +
> +#ifdef DEBUG
> +	printk
> +	    (KERN_DEBUG "i2c-i801.o: Transaction (pre): CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
> +	     "DAT1=%02x\n", inb_p(SMBHSTCNT), inb_p(SMBHSTCMD),
> +	     inb_p(SMBHSTADD), inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1));
> +#endif

pr_debug

> +		temp = inb_p(SMBHSTSTS);
> +                if (i = 1) {
> +                    /* Erronenous conditions before transaction: 
> +                     * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
> +                    errmask=0x9f; 
> +                } else {
> +                    /* Erronenous conditions during transaction: 
> +                     * Failed, Bus_Err, Dev_Err, Intr */
> +                    errmask=0x1e; 
> +                }

Indentation look b0rked.

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23         ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, sensors

On Fri, Mar 14, 2003 at 08:21:42AM +0000, Christoph Hellwig wrote:
> On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> > ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com
> > 
> > i2c: get i2c-ali15x3 driver to actually bind to a PCI device.
> 
> OOPS, should take a look at all patches first before complaining :)

Heh :)

Yes, for the first changeset I just took the cvs version of the driver
and added it.

Then I went and made the driver work, and started to clean it up.  These
drivers still need a lot of cleanup (static, printk, indentation in
places, etc.) and I'll be doing it.  This is a work in progress.  I
wanted to make baby steps with these things and not just do one
changeset with a description that said:
	Took cvs version of driver and cleaned up everything

I'm trying to bridge the gap between the sensor developers and the
kernel group.  Hopefully by working this way it will help integrate them
more into the kernel community, and get these drivers whipped into
shape.

thanks for looking these over.

greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23       ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Christoph Hellwig, linux-kernel, sensors

On Fri, Mar 14, 2003 at 08:19:04AM +0000, Christoph Hellwig wrote:
> > +/* Internally used pause function */
> > +void ali15x3_do_pause(unsigned int amount)
> > +{
> > +	current->state = TASK_INTERRUPTIBLE;
> > +	schedule_timeout(amount);
> > +}
> 
> I think this should be moved to linux/kernel.h as delay() - I've seen
> it duplicated in so much code (including XFS)

I'll move this.  I think I have this in the usb.h header file too :)

> > +#ifdef DEBUG
> > +	printk
> > +	    ("i2c-ali15x3.o: Transaction (pre): STS=%02x, CNT=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, "
> > +	     "DAT1=%02x\n", inb_p(SMBHSTSTS), inb_p(SMBHSTCNT),
> > +	     inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
> > +	     inb_p(SMBHSTDAT1));
> > +#endif
> 
> use pr_debug() here.

In the next round of patches I'm using dev_dbg() and other dev_*
functions for the printk calls, now that we have device support for the
adapters.

thanks,

greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23                       ` Vojtech Pavlik
  0 siblings, 0 replies; 47+ messages in thread
From: Vojtech Pavlik @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Greg KH; +Cc: linux-kernel, sensors

On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:

> diff -Nru a/drivers/i2c/busses/i2c-amd8111.c b/drivers/i2c/busses/i2c-amd8111.c
> --- a/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
> +++ b/drivers/i2c/busses/i2c-amd8111.c	Thu Mar 13 16:56:52 2003
 		goto out_release_region;
> @@ -389,7 +392,7 @@
>  }
>  
>  static struct pci_driver amd8111_driver = {
> -	.name		= "amd8111 smbus 2.0",
> +	.name		= "amd8111 smbus",
>  	.id_table	= amd8111_ids,
>  	.probe		= amd8111_probe,
>  	.remove		= __devexit_p(amd8111_remove),

The 2.0 was quite intentional in the .name, because the 8111 has *two*
SMBus busses, one SMBus 1.1 and one SMBus 2.0. This driver is only for
the 2.0 SMBus controller.

-- 
Vojtech Pavlik
SuSE Labs

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23                         ` Greg KH
  0 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Vojtech Pavlik; +Cc: linux-kernel, sensors

On Sat, Mar 15, 2003 at 10:49:01AM +0100, Vojtech Pavlik wrote:
> On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> >  static struct pci_driver amd8111_driver = {
> > -	.name		= "amd8111 smbus 2.0",
> > +	.name		= "amd8111 smbus",
> 
> The 2.0 was quite intentional in the .name, because the 8111 has *two*
> SMBus busses, one SMBus 1.1 and one SMBus 2.0. This driver is only for
> the 2.0 SMBus controller.

Ah, I removed the "2.0" portion because it was larger than the 16
character limit for pci driver names (it shows up in sysfs garbled if
it's bigger).

Would "amd8111 smbus 2" be an ok name?

thanks,

greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
@ 2005-05-19  6:23                           ` Vojtech Pavlik
  0 siblings, 0 replies; 47+ messages in thread
From: Vojtech Pavlik @ 2005-05-19  6:23 UTC (permalink / raw)
  To: Greg KH; +Cc: Vojtech Pavlik, linux-kernel, sensors

On Sat, Mar 15, 2003 at 01:46:23PM -0800, Greg KH wrote:
> On Sat, Mar 15, 2003 at 10:49:01AM +0100, Vojtech Pavlik wrote:
> > On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
> > >  static struct pci_driver amd8111_driver = {
> > > -	.name		= "amd8111 smbus 2.0",
> > > +	.name		= "amd8111 smbus",
> > 
> > The 2.0 was quite intentional in the .name, because the 8111 has *two*
> > SMBus busses, one SMBus 1.1 and one SMBus 2.0. This driver is only for
> > the 2.0 SMBus controller.
> 
> Ah, I removed the "2.0" portion because it was larger than the 16
> character limit for pci driver names (it shows up in sysfs garbled if
> it's bigger).
> 
> Would "amd8111 smbus 2" be an ok name?

Yes.

-- 
Vojtech Pavlik
SuSE Labs

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (2 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Mark D. Studebaker 
  -1 siblings, 0 replies; 47+ messages in thread
From: Mark D. Studebaker  @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors

Greg,

I'm catching up on my mail. Glad to have you on the job.
It's good you are taking things from CVS.
As you may know, Kyosti Malkki did a lot of cleanup and
pre-2.4.9 compatiblility removal in January.
He branched i2c CVS (with the HEAD 2.5-compatible).
Lm_sensors CVS is not branched.

The biggest thing remaining to do in CVS is tackling
the PCI drivers. Approx. 20 of our 60 drivers are PCI.

I'd like to keep sensors CVS 2.4-compatible, or at least
delay a branch as long as possible. Kyosti was working
on getting to the point that we could submit a patch
to 2.4 (until we do that, CVS is incompatible with stock 2.4
kernels because of the i2c_driver struct change).
Any sensors changes/cleanups that are 2.4 compatible,
it's preferable to check those changes into CVS
for testing. Ideally we can submit drivers to 2.5 directly
out of CVS.

mds


Greg KH wrote:
> On Fri, Mar 14, 2003 at 08:21:42AM +0000, Christoph Hellwig wrote:
> 
>>On Thu, Mar 13, 2003 at 04:55:00PM -0800, Greg KH wrote:
>>
>>>ChangeSet 1.1106, 2003/03/13 10:50:41-08:00, greg@kroah.com
>>>
>>>i2c: get i2c-ali15x3 driver to actually bind to a PCI device.
>>
>>OOPS, should take a look at all patches first before complaining :)
> 
> 
> Heh :)
> 
> Yes, for the first changeset I just took the cvs version of the driver
> and added it.
> 
> Then I went and made the driver work, and started to clean it up.  These
> drivers still need a lot of cleanup (static, printk, indentation in
> places, etc.) and I'll be doing it.  This is a work in progress.  I
> wanted to make baby steps with these things and not just do one
> changeset with a description that said:
> 	Took cvs version of driver and cleaned up everything
> 
> I'm trying to bridge the gap between the sensor developers and the
> kernel group.  Hopefully by working this way it will help integrate them
> more into the kernel community, and get these drivers whipped into
> shape.
> 
> thanks for looking these over.
> 
> greg k-h
> 

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (6 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors

On Mon, Mar 17, 2003 at 08:17:14PM -0500, Mark D. Studebaker  wrote:
> 
> I'm catching up on my mail. Glad to have you on the job.

Thanks.

> It's good you are taking things from CVS.
> As you may know, Kyosti Malkki did a lot of cleanup and
> pre-2.4.9 compatiblility removal in January.
> He branched i2c CVS (with the HEAD 2.5-compatible).
> Lm_sensors CVS is not branched.

So where should I be looking to get the latest kernel code?  It looks
like the kernel files in drivers/i2c/ are in the i2c CVS's kernel/
directory, right?

And then the kernel drivers/i2c/busses/ and drivers/i2c/chips match up
with the lm_sensors2 CVS's kernel/busses and kernel/chips directories?

If so, any hope of merging the two to make it at least sane?  :)

> The biggest thing remaining to do in CVS is tackling
> the PCI drivers. Approx. 20 of our 60 drivers are PCI.

Where are these drivers?  I only see 17 instances of pci_module_init()
in the lm_sensors2 cvs tree.  Are these the ones?  If you look at
2.5.65, 3 ones were added from the cvs tree (and converted to work
properly with the pci code.)  I see there are only 5 drivers in the main
kernel tree that use pci_module_init() so a number more still need to be
moved into there.

> I'd like to keep sensors CVS 2.4-compatible, or at least
> delay a branch as long as possible. Kyosti was working
> on getting to the point that we could submit a patch
> to 2.4 (until we do that, CVS is incompatible with stock 2.4
> kernels because of the i2c_driver struct change).

Why care about backwards compatibility?  Hopefully there will not need
to be a cvs tree for the kernel portions of the i2c code if we get all
of the code into the main kernel tree.

It's tough to develop code in a cvs tree and then move that into the
main kernel tree (trust me, I've done it for years...)  It's much easier
once the code is in the main kernel, to just work off of those versions,
possibly keeping a few patches along as they are developed, before they
are accepted in the main kernel trees.  I've successfully done this for
the pci hotplug code for 2.4 and 2.5, and the usb code for 2.2, 2.4, and
2.5.

Also, kernel code over kernel major versions differs a lot.  Already the
i2c code is branched due to the driver model changes, and that will also
cause more changes in the future (all good :)

> Any sensors changes/cleanups that are 2.4 compatible,
> it's preferable to check those changes into CVS
> for testing. Ideally we can submit drivers to 2.5 directly
> out of CVS.

Are there any test scripts or procedures that one should go through to
determine if any changes break anything or not?

thanks,

greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (3 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Mark D. Studebaker 
  -1 siblings, 0 replies; 47+ messages in thread
From: Mark D. Studebaker  @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors



Greg KH wrote:
> On Mon, Mar 17, 2003 at 08:17:14PM -0500, Mark D. Studebaker  wrote:
> 
>>I'm catching up on my mail. Glad to have you on the job.
> 
> 
> Thanks.
> 
> 
>>It's good you are taking things from CVS.
>>As you may know, Kyosti Malkki did a lot of cleanup and
>>pre-2.4.9 compatiblility removal in January.
>>He branched i2c CVS (with the HEAD 2.5-compatible).
>>Lm_sensors CVS is not branched.
> 
> 
> So where should I be looking to get the latest kernel code?  It looks
> like the kernel files in drivers/i2c/ are in the i2c CVS's kernel/
> directory, right?
> 

right

> And then the kernel drivers/i2c/busses/ and drivers/i2c/chips match up
> with the lm_sensors2 CVS's kernel/busses and kernel/chips directories?
> 

right

> If so, any hope of merging the two to make it at least sane?  :)
> 

sounds like more trouble than it is worth;
hard to move files in CVS without losing the history.

> 
>>The biggest thing remaining to do in CVS is tackling
>>the PCI drivers. Approx. 20 of our 60 drivers are PCI.
> 
> 
> Where are these drivers?  I only see 17 instances of pci_module_init()
> in the lm_sensors2 cvs tree.  Are these the ones?  If you look at
> 2.5.65, 3 ones were added from the cvs tree (and converted to work
> properly with the pci code.)  I see there are only 5 drivers in the main
> kernel tree that use pci_module_init() so a number more still need to be
> moved into there.
> 

right. Plus a couple more in chips/ that don't call pci_module_init
(sis5595, vt8231). Minus the ones already in 2.5 (I see that
2.5.65 added your patch with 3 more) leaves about 15.

My point was the ~40 non-PCI drivers should go a lot more easily;
Kyosti already did a lot of cleanup on those.

> 
>>I'd like to keep sensors CVS 2.4-compatible, or at least
>>delay a branch as long as possible. Kyosti was working
>>on getting to the point that we could submit a patch
>>to 2.4 (until we do that, CVS is incompatible with stock 2.4
>>kernels because of the i2c_driver struct change).
> 
> 
> Why care about backwards compatibility?  Hopefully there will not need
> to be a cvs tree for the kernel portions of the i2c code if we get all
> of the code into the main kernel tree.
> 

We have a large number of 2.4-based "customers". Our project is
ranked in the top 100 on freshmeat (no idea if that means anything, though :)
If our 2.7.0 release last December was the last 2.4-compatible release,
how bad is that? I don't know. Unless we get a patch into 2.4, it will be,
because of the i2c_driver struct change that's already been made in CVS.
I'm guessing we want to release 2.4-compatible packages for another year?
But maybe that's hopelessly ambitious. Maybe 2.7.0 will have to be it.
Kyosti was optimistic that on the lm_sensors side (as opposed to i2c),
we could stay compatible with 2.4 and 2.5 in one branch. But he
hasn't been heard from in a while...

> It's tough to develop code in a cvs tree and then move that into the
> main kernel tree (trust me, I've done it for years...)  It's much easier
> once the code is in the main kernel, to just work off of those versions,
> possibly keeping a few patches along as they are developed, before they
> are accepted in the main kernel trees.  I've successfully done this for
> the pci hotplug code for 2.4 and 2.5, and the usb code for 2.2, 2.4, and
> 2.5.
> 
> Also, kernel code over kernel major versions differs a lot.  Already the
> i2c code is branched due to the driver model changes, and that will also
> cause more changes in the future (all good :)
> 

I'm not disagreeing with you. Maybe it's easier with our collection of
small drivers. Maybe not. Maybe it only makes sense for drivers not
yet in the kernel.

> 
>>Any sensors changes/cleanups that are 2.4 compatible,
>>it's preferable to check those changes into CVS
>>for testing. Ideally we can submit drivers to 2.5 directly
>>out of CVS.
> 
> 
> Are there any test scripts or procedures that one should go through to
> determine if any changes break anything or not?
> 

Nothing formal.
You can send the group mail and ask for testing. I have a pretty good collection of HW.
For bus drivers, if you're lucky enough to have HW to test on,
you should try i2cdetect, and i2cdump (with different modes).
For chip drivers, even if you don't have the hardware, it's
good to load the module with a force_xxx parameter and
then try 'sensors' and look in /proc.

> thanks,
> 
> greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (7 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors

On Mon, Mar 17, 2003 at 09:28:41PM -0500, Mark D. Studebaker  wrote:
> >If so, any hope of merging the two to make it at least sane?  :)
> >
> 
> sounds like more trouble than it is worth;
> hard to move files in CVS without losing the history.

True, but it seems strange to have files in two different repositories.
But I now see why you did that because of the 2.4 code, right?  Anyway,
I'll live :)

> >>The biggest thing remaining to do in CVS is tackling
> >>the PCI drivers. Approx. 20 of our 60 drivers are PCI.
> >
> >
> >Where are these drivers?  I only see 17 instances of pci_module_init()
> >in the lm_sensors2 cvs tree.  Are these the ones?  If you look at
> >2.5.65, 3 ones were added from the cvs tree (and converted to work
> >properly with the pci code.)  I see there are only 5 drivers in the main
> >kernel tree that use pci_module_init() so a number more still need to be
> >moved into there.
> >
> 
> right. Plus a couple more in chips/ that don't call pci_module_init
> (sis5595, vt8231). Minus the ones already in 2.5 (I see that
> 2.5.65 added your patch with 3 more) leaves about 15.
> 
> My point was the ~40 non-PCI drivers should go a lot more easily;
> Kyosti already did a lot of cleanup on those.

Good, I haven't really looked at them yet.

> >>I'd like to keep sensors CVS 2.4-compatible, or at least
> >>delay a branch as long as possible. Kyosti was working
> >>on getting to the point that we could submit a patch
> >>to 2.4 (until we do that, CVS is incompatible with stock 2.4
> >>kernels because of the i2c_driver struct change).
> >
> >
> >Why care about backwards compatibility?  Hopefully there will not need
> >to be a cvs tree for the kernel portions of the i2c code if we get all
> >of the code into the main kernel tree.
> >
> 
> We have a large number of 2.4-based "customers". Our project is
> ranked in the top 100 on freshmeat (no idea if that means anything, though 
> :)
> If our 2.7.0 release last December was the last 2.4-compatible release,
> how bad is that? I don't know. Unless we get a patch into 2.4, it will be,
> because of the i2c_driver struct change that's already been made in CVS.
> I'm guessing we want to release 2.4-compatible packages for another year?

You've already forked the cvs tree, right?  What's keeping you from just
staying with this fork for the 2.4 code?

> But maybe that's hopelessly ambitious. Maybe 2.7.0 will have to be it.
> Kyosti was optimistic that on the lm_sensors side (as opposed to i2c),
> we could stay compatible with 2.4 and 2.5 in one branch. But he
> hasn't been heard from in a while...

I'm not so sure about that due to the driver model changes, but am not
certain yet.  I'll shut up now until I get some more code done...

thanks,

greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (5 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Christoph Hellwig
  -1 siblings, 0 replies; 47+ messages in thread
From: Christoph Hellwig @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors

On Mon, Mar 17, 2003 at 08:17:14PM -0500, Mark D. Studebaker  wrote:
> I'd like to keep sensors CVS 2.4-compatible, or at least
> delay a branch as long as possible.

With Greg's driver model changes the code won't compile under 2.4 anymore.
But I think it might be possible to supply stubs for that functionality
so that the drivers can be used on 2.4 aswell.

> Kyosti was working
> on getting to the point that we could submit a patch
> to 2.4 (until we do that, CVS is incompatible with stock 2.4
> kernels because of the i2c_driver struct change).
> Any sensors changes/cleanups that are 2.4 compatible,
> it's preferable to check those changes into CVS
> for testing. Ideally we can submit drivers to 2.5 directly
> out of CVS.

Submitting out of CVS is bad, this leads to the usualy "CVS mentality"
with resyncs instead of properly one thing at a time changes.

What do you think about having them in 2.5 first and then put them into
CVS for the 2.4 backport (which in the best case is not a port at all
but just the addition of a compatiblity header).

I'm happy to help out with feeding the sensors changes to Linus and
review / fix smaller issues.

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (4 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Mark D. Studebaker 
  -1 siblings, 0 replies; 47+ messages in thread
From: Mark D. Studebaker  @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors



Greg KH wrote:
> On Mon, Mar 17, 2003 at 09:28:41PM -0500, Mark D. Studebaker  wrote:
> 
>>>If so, any hope of merging the two to make it at least sane?  :)
>>>
>>
>>sounds like more trouble than it is worth;
>>hard to move files in CVS without losing the history.
> 
> 
> True, but it seems strange to have files in two different repositories.
> But I now see why you did that because of the 2.4 code, right?  Anyway,
> I'll live :)
> 

No. The i2c and sensors projects were started by different people in
different places. In 1999, the i2c project was moved to be hosted
at Netroedge, where the sensors project was already.
It was put in a separate CVS tree. Over the last couple of
years the original i2c contributors have moved on.
But the separate trees remain.

> 
>>>>The biggest thing remaining to do in CVS is tackling
>>>>the PCI drivers. Approx. 20 of our 60 drivers are PCI.
>>>
>>>
>>>Where are these drivers?  I only see 17 instances of pci_module_init()
>>>in the lm_sensors2 cvs tree.  Are these the ones?  If you look at
>>>2.5.65, 3 ones were added from the cvs tree (and converted to work
>>>properly with the pci code.)  I see there are only 5 drivers in the main
>>>kernel tree that use pci_module_init() so a number more still need to be
>>>moved into there.
>>>
>>
>>right. Plus a couple more in chips/ that don't call pci_module_init
>>(sis5595, vt8231). Minus the ones already in 2.5 (I see that
>>2.5.65 added your patch with 3 more) leaves about 15.
>>
>>My point was the ~40 non-PCI drivers should go a lot more easily;
>>Kyosti already did a lot of cleanup on those.
> 
> 
> Good, I haven't really looked at them yet.
> 
> 
>>>>I'd like to keep sensors CVS 2.4-compatible, or at least
>>>>delay a branch as long as possible. Kyosti was working
>>>>on getting to the point that we could submit a patch
>>>>to 2.4 (until we do that, CVS is incompatible with stock 2.4
>>>>kernels because of the i2c_driver struct change).
>>>
>>>
>>>Why care about backwards compatibility?  Hopefully there will not need
>>>to be a cvs tree for the kernel portions of the i2c code if we get all
>>>of the code into the main kernel tree.
>>>
>>
>>We have a large number of 2.4-based "customers". Our project is
>>ranked in the top 100 on freshmeat (no idea if that means anything, though 
>>:)
>>If our 2.7.0 release last December was the last 2.4-compatible release,
>>how bad is that? I don't know. Unless we get a patch into 2.4, it will be,
>>because of the i2c_driver struct change that's already been made in CVS.
>>I'm guessing we want to release 2.4-compatible packages for another year?
> 
> 
> You've already forked the cvs tree, right?  What's keeping you from just
> staying with this fork for the 2.4 code?
> 
> 
>>But maybe that's hopelessly ambitious. Maybe 2.7.0 will have to be it.
>>Kyosti was optimistic that on the lm_sensors side (as opposed to i2c),
>>we could stay compatible with 2.4 and 2.5 in one branch. But he
>>hasn't been heard from in a while...
> 
> 
> I'm not so sure about that due to the driver model changes, but am not
> certain yet.  I'll shut up now until I get some more code done...
> 

guess I missed something, exactly what are the "driver model changes"?
I see a new adapter.dev.parent in the bus drivers, is that it?
Are there any changes affecting the chip drivers? I didn't see any.

> thanks,
> 
> greg k-h
> 

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
  (?)
  (?)
@ 2005-05-19  6:23         ` Greg KH
  -1 siblings, 0 replies; 47+ messages in thread
From: Greg KH @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors

On Wed, Mar 19, 2003 at 09:21:37PM -0500, Mark D. Studebaker  wrote:
> 
> No. The i2c and sensors projects were started by different people in
> different places. In 1999, the i2c project was moved to be hosted
> at Netroedge, where the sensors project was already.
> It was put in a separate CVS tree. Over the last couple of
> years the original i2c contributors have moved on.
> But the separate trees remain.

Ah, that makes more sense now, thanks for the history lesson.

> guess I missed something, exactly what are the "driver model changes"?

Converting the i2c core, and all drivers over to the kernel driver
model.  See include/linux/device.h for the structures and
Documentation/driver-model/* for lots of documentation.  Also, Pat
Mochel has written a lot of good documentation at:
	http://www.kernel.org/pub/linux/kernel/people/mochel/doc/lca/driver-model-lca2003.tar.gz

It basically involves hooking the drivers and core up to the rest of the
kernel, like I've already done.  All of the kernel's drivers are either
already converted to this model, or are in the process of being
converted.

> I see a new adapter.dev.parent in the bus drivers, is that it?

For now, yes.

> Are there any changes affecting the chip drivers? I didn't see any.

Not yet.  If you look at my original patch I sent to the list, I do hook
up the chip drivers to the driver core, but don't do much with them.  I
didn't include that portion in my patches to Linus as it needs some more
work to get everything working properly.

Does this help explain stuff?  I hope to have a more concrete set of
patches soon to show what I'm talking about (code is sometimes easier to
understand than documentation :)

thanks,

greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (9 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Mark Studebaker
  -1 siblings, 0 replies; 47+ messages in thread
From: Mark Studebaker @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors

thanks for the driver model links, that's what I needed.

Greg KH wrote:
> 
> On Wed, Mar 19, 2003 at 09:21:37PM -0500, Mark D. Studebaker  wrote:
> >
> > No. The i2c and sensors projects were started by different people in
> > different places. In 1999, the i2c project was moved to be hosted
> > at Netroedge, where the sensors project was already.
> > It was put in a separate CVS tree. Over the last couple of
> > years the original i2c contributors have moved on.
> > But the separate trees remain.
> 
> Ah, that makes more sense now, thanks for the history lesson.
> 
> > guess I missed something, exactly what are the "driver model changes"?
> 
> Converting the i2c core, and all drivers over to the kernel driver
> model.  See include/linux/device.h for the structures and
> Documentation/driver-model/* for lots of documentation.  Also, Pat
> Mochel has written a lot of good documentation at:
>         http://www.kernel.org/pub/linux/kernel/people/mochel/doc/lca/driver-model-lca2003.tar.gz
> 
> It basically involves hooking the drivers and core up to the rest of the
> kernel, like I've already done.  All of the kernel's drivers are either
> already converted to this model, or are in the process of being
> converted.
> 
> > I see a new adapter.dev.parent in the bus drivers, is that it?
> 
> For now, yes.
> 
> > Are there any changes affecting the chip drivers? I didn't see any.
> 
> Not yet.  If you look at my original patch I sent to the list, I do hook
> up the chip drivers to the driver core, but don't do much with them.  I
> didn't include that portion in my patches to Linus as it needs some more
> work to get everything working properly.
> 
> Does this help explain stuff?  I hope to have a more concrete set of
> patches soon to show what I'm talking about (code is sometimes easier to
> understand than documentation :)
> 
> thanks,
> 
> greg k-h

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

* [PATCH] i2c driver changes for 2.5.64
  2005-05-19  6:23         ` Greg KH
                           ` (8 preceding siblings ...)
  (?)
@ 2005-05-19  6:23         ` Jean Delvare
  -1 siblings, 0 replies; 47+ messages in thread
From: Jean Delvare @ 2005-05-19  6:23 UTC (permalink / raw)
  To: lm-sensors


> > If so, any hope of merging the two to make it at least sane?  :)
> 
> sounds like more trouble than it is worth;
> hard to move files in CVS without losing the history.

Actually, I read the CVS docs some days ago, and there seem to be a
command for that. See there:
http://www.cvshome.org/docs/manual/cvs_7.html#SEC70

OK, doesn't sound easy, but not impossible. What about using method 1
(7.4.1 in the docs) and simply add some header comment in the new file
stating the old name, so that one can get the history if needed?

(...)

> > Why care about backwards compatibility?  Hopefully there will not
> > need to be a cvs tree for the kernel portions of the i2c code if we
> > get all of the code into the main kernel tree.
> > 
> 
> We have a large number of 2.4-based "customers". Our project is
> ranked in the top 100 on freshmeat (no idea if that means anything,
> though :) If our 2.7.0 release last December was the last
> 2.4-compatible release, how bad is that? I don't know. Unless we get a
> patch into 2.4, it will be, because of the i2c_driver struct change
> that's already been made in CVS. I'm guessing we want to release
> 2.4-compatible packages for another year? But maybe that's hopelessly
> ambitious. Maybe 2.7.0 will have to be it. Kyosti was optimistic that
> on the lm_sensors side (as opposed to i2c), we could stay compatible
> with 2.4 and 2.5 in one branch. But he hasn't been heard from in a
> while...

I really think we shouldn't give our preference to compatibility over
code cleanness. We could simply keep 2.7.0 as our pre-heavy-work
release, and do the minimum bugfixes to it when required, no more. Once
"everything" is integrated into the kernel (and you have gone too far
already for this not to happen), nobody will care about the old code
anymore, so I don't think it's clever to spend too many time on it.

Just my opinion, though.

-- 
Jean Delvare
http://www.ensicaen.ismra.fr/~delvare/

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

end of thread, other threads:[~2005-05-19  6:23 UTC | newest]

Thread overview: 47+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2003-03-14  0:50 [BK PATCH] i2c driver changes for 2.5.64 Greg KH
2005-05-19  6:23 ` Greg KH
2003-03-14  0:55 ` [PATCH] " Greg KH
2005-05-19  6:23   ` Greg KH
2003-03-14  0:55   ` Greg KH
2005-05-19  6:23     ` Greg KH
2003-03-14  0:55     ` Greg KH
2005-05-19  6:23       ` Greg KH
2003-03-14  0:55       ` Greg KH
2005-05-19  6:23         ` Greg KH
2003-03-14  0:55         ` Greg KH
2005-05-19  6:23           ` Greg KH
2003-03-14  0:55           ` Greg KH
2005-05-19  6:23             ` Greg KH
2003-03-14  0:55             ` Greg KH
2005-05-19  6:23               ` Greg KH
2003-03-14  0:55               ` Greg KH
2005-05-19  6:23                 ` Greg KH
2003-03-14  0:55                 ` Greg KH
2005-05-19  6:23                   ` Greg KH
2003-03-14  0:55                   ` Greg KH
2005-05-19  6:23                     ` Greg KH
2003-03-15  9:49                     ` Vojtech Pavlik
2005-05-19  6:23                       ` Vojtech Pavlik
2003-03-15 21:46                       ` Greg KH
2005-05-19  6:23                         ` Greg KH
2003-03-15 22:06                         ` Vojtech Pavlik
2005-05-19  6:23                           ` Vojtech Pavlik
2005-05-19  6:23         ` Greg KH
2005-05-19  6:23         ` Mark D. Studebaker 
2005-05-19  6:23         ` Mark D. Studebaker 
2005-05-19  6:23         ` Mark D. Studebaker 
2005-05-19  6:23         ` Christoph Hellwig
2005-05-19  6:23         ` Greg KH
2005-05-19  6:23         ` Greg KH
2005-05-19  6:23         ` Jean Delvare
2005-05-19  6:23         ` Mark Studebaker
2003-03-14  8:28       ` Christoph Hellwig
2005-05-19  6:23         ` Christoph Hellwig
2003-03-14  8:21     ` Christoph Hellwig
2005-05-19  6:23       ` Christoph Hellwig
2003-03-14  8:53       ` Greg KH
2005-05-19  6:23         ` Greg KH
2003-03-14  8:19   ` Christoph Hellwig
2005-05-19  6:23     ` Christoph Hellwig
2003-03-14  8:56     ` Greg KH
2005-05-19  6:23       ` Greg KH

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.