Browse Source

Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6

* master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6: (30 commits)
  i2c: Drop unimplemented slave functions
  i2c: Constify i2c_algorithm declarations, part 2
  i2c: Constify i2c_algorithm declarations, part 1
  i2c: Let drivers constify i2c_algorithm data
  i2c-isa: Restore driver owner
  i2c-viapro: Add support for the VT8237A and VT8251
  i2c: Warn on i2c client creation failure
  i2c-core: Drop useless bitmaskings
  i2c-algo-pcf: Discard the mdelay data struct member
  i2c-algo-bit: Cleanups
  i2c-isa: Fail adding driver on attach_adapter error
  i2c: __must_check fixes (chip drivers)
  i2c-dev: attach/detach_adapter cleanups
  i2c-stub: Chip address as a module parameter
  i2c: Plan i2c-isa for removal
  i2c: New bus driver for TI OMAP boards
  i2c-algo-bit: Discard the mdelay data struct member
  i2c-matroxfb: Struct init conversion
  i2c: Fix copy-n-paste in subsystem Kconfig
  i2c-au1550: Add I2C support for Au1200
  ...
Linus Torvalds 18 years ago
parent
commit
a5b08073a0
83 changed files with 1219 additions and 482 deletions
  1. 9 0
      Documentation/feature-removal-schedule.txt
  2. 6 1
      Documentation/i2c/busses/i2c-viapro
  3. 13 2
      Documentation/i2c/i2c-stub
  4. 0 1
      drivers/acorn/char/i2c.c
  5. 1 1
      drivers/acpi/i2c_ec.c
  6. 1 0
      drivers/hwmon/it87.c
  7. 1 0
      drivers/hwmon/lm78.c
  8. 1 0
      drivers/hwmon/pc87360.c
  9. 1 0
      drivers/hwmon/sis5595.c
  10. 1 0
      drivers/hwmon/smsc47b397.c
  11. 1 0
      drivers/hwmon/smsc47m1.c
  12. 1 0
      drivers/hwmon/via686a.c
  13. 1 0
      drivers/hwmon/vt8231.c
  14. 1 0
      drivers/hwmon/w83627ehf.c
  15. 1 0
      drivers/hwmon/w83627hf.c
  16. 1 0
      drivers/hwmon/w83781d.c
  17. 1 1
      drivers/i2c/Kconfig
  18. 0 6
      drivers/i2c/algos/Kconfig
  19. 0 1
      drivers/i2c/algos/Makefile
  20. 9 14
      drivers/i2c/algos/i2c-algo-bit.c
  21. 1 1
      drivers/i2c/algos/i2c-algo-pca.c
  22. 1 1
      drivers/i2c/algos/i2c-algo-pcf.c
  23. 1 1
      drivers/i2c/algos/i2c-algo-sgi.c
  24. 0 215
      drivers/i2c/algos/i2c-algo-sibyte.c
  25. 22 12
      drivers/i2c/busses/Kconfig
  26. 1 0
      drivers/i2c/busses/Makefile
  27. 1 1
      drivers/i2c/busses/i2c-ali1535.c
  28. 1 1
      drivers/i2c/busses/i2c-ali1563.c
  29. 1 1
      drivers/i2c/busses/i2c-ali15x3.c
  30. 1 1
      drivers/i2c/busses/i2c-amd756.c
  31. 1 1
      drivers/i2c/busses/i2c-amd8111.c
  32. 13 8
      drivers/i2c/busses/i2c-au1550.c
  33. 0 1
      drivers/i2c/busses/i2c-elektor.c
  34. 0 1
      drivers/i2c/busses/i2c-hydra.c
  35. 1 1
      drivers/i2c/busses/i2c-i801.c
  36. 0 2
      drivers/i2c/busses/i2c-i810.c
  37. 1 1
      drivers/i2c/busses/i2c-ibm_iic.c
  38. 1 1
      drivers/i2c/busses/i2c-iop3xx.c
  39. 35 7
      drivers/i2c/busses/i2c-isa.c
  40. 0 1
      drivers/i2c/busses/i2c-ixp2000.c
  41. 0 1
      drivers/i2c/busses/i2c-ixp4xx.c
  42. 1 1
      drivers/i2c/busses/i2c-mpc.c
  43. 1 1
      drivers/i2c/busses/i2c-mv64xxx.c
  44. 1 1
      drivers/i2c/busses/i2c-nforce2.c
  45. 1 1
      drivers/i2c/busses/i2c-ocores.c
  46. 676 0
      drivers/i2c/busses/i2c-omap.c
  47. 0 1
      drivers/i2c/busses/i2c-parport-light.c
  48. 0 1
      drivers/i2c/busses/i2c-parport.c
  49. 1 1
      drivers/i2c/busses/i2c-piix4.c
  50. 1 1
      drivers/i2c/busses/i2c-powermac.c
  51. 0 1
      drivers/i2c/busses/i2c-prosavage.c
  52. 1 1
      drivers/i2c/busses/i2c-pxa.c
  53. 1 1
      drivers/i2c/busses/i2c-s3c2410.c
  54. 0 1
      drivers/i2c/busses/i2c-savage4.c
  55. 156 4
      drivers/i2c/busses/i2c-sibyte.c
  56. 1 1
      drivers/i2c/busses/i2c-sis5595.c
  57. 1 1
      drivers/i2c/busses/i2c-sis630.c
  58. 1 1
      drivers/i2c/busses/i2c-sis96x.c
  59. 19 2
      drivers/i2c/busses/i2c-stub.c
  60. 0 1
      drivers/i2c/busses/i2c-via.c
  61. 9 1
      drivers/i2c/busses/i2c-viapro.c
  62. 0 2
      drivers/i2c/busses/i2c-voodoo3.c
  63. 1 1
      drivers/i2c/busses/scx200_acb.c
  64. 6 6
      drivers/i2c/busses/scx200_i2c.c
  65. 7 1
      drivers/i2c/chips/eeprom.c
  66. 19 6
      drivers/i2c/chips/max6875.c
  67. 9 2
      drivers/i2c/chips/pca9539.c
  68. 17 5
      drivers/i2c/chips/pcf8574.c
  69. 45 13
      drivers/i2c/chips/pcf8591.c
  70. 55 17
      drivers/i2c/i2c-core.c
  71. 50 59
      drivers/i2c/i2c-dev.c
  72. 0 1
      drivers/ieee1394/pcilynx.c
  73. 0 1
      drivers/media/video/bt8xx/bttv-i2c.c
  74. 0 1
      drivers/media/video/cx88/cx88-i2c.c
  75. 0 1
      drivers/media/video/cx88/cx88-vp3054-i2c.c
  76. 0 1
      drivers/media/video/zoran_card.c
  77. 0 1
      drivers/video/i810/i810-i2c.c
  78. 6 6
      drivers/video/matrox/i2c-matroxfb.c
  79. 0 1
      drivers/video/savage/savagefb-i2c.c
  80. 0 1
      include/linux/i2c-algo-bit.h
  81. 0 1
      include/linux/i2c-algo-pcf.h
  82. 0 33
      include/linux/i2c-algo-sibyte.h
  83. 1 13
      include/linux/i2c.h

+ 9 - 0
Documentation/feature-removal-schedule.txt

@@ -313,3 +313,12 @@ Why:	The stacking of class devices makes these values misleading and
 Who:	Kay Sievers <kay.sievers@suse.de>
 
 ---------------------------
+
+What:	i2c-isa
+When:	December 2006
+Why:	i2c-isa is a non-sense and doesn't fit in the device driver
+	model. Drivers relying on it are better implemented as platform
+	drivers.
+Who:	Jean Delvare <khali@linux-fr.org>
+
+---------------------------

+ 6 - 1
Documentation/i2c/busses/i2c-viapro

@@ -7,9 +7,12 @@ Supported adapters:
   * VIA Technologies, Inc. VT82C686A/B
     Datasheet: Sometimes available at the VIA website
 
-  * VIA Technologies, Inc. VT8231, VT8233, VT8233A, VT8235, VT8237R
+  * VIA Technologies, Inc. VT8231, VT8233, VT8233A
     Datasheet: available on request from VIA
 
+  * VIA Technologies, Inc. VT8235, VT8237R, VT8237A, VT8251
+    Datasheet: available on request and under NDA from VIA
+
 Authors:
 	Kyösti Mälkki <kmalkki@cc.hut.fi>,
 	Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -39,6 +42,8 @@ Your lspci -n listing must show one of these :
  device 1106:8235   (VT8231 function 4)
  device 1106:3177   (VT8235)
  device 1106:3227   (VT8237R)
+ device 1106:3337   (VT8237A)
+ device 1106:3287   (VT8251)
 
 If none of these show up, you should look in the BIOS for settings like
 enable ACPI / SMBus or even USB.

+ 13 - 2
Documentation/i2c/i2c-stub

@@ -6,9 +6,12 @@ This module is a very simple fake I2C/SMBus driver.  It implements four
 types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, and
 (r/w) word data.
 
+You need to provide a chip address as a module parameter when loading
+this driver, which will then only react to SMBus commands to this address.
+
 No hardware is needed nor associated with this module.  It will accept write
-quick commands to all addresses; it will respond to the other commands (also
-to all addresses) by reading from or writing to an array in memory.  It will
+quick commands to one address; it will respond to the other commands (also
+to one address) by reading from or writing to an array in memory.  It will
 also spam the kernel logs for every command it handles.
 
 A pointer register with auto-increment is implemented for all byte
@@ -21,6 +24,11 @@ The typical use-case is like this:
 	3. load the target sensors chip driver module
 	4. observe its behavior in the kernel log
 
+PARAMETERS:
+
+int chip_addr:
+	The SMBus address to emulate a chip at.
+
 CAVEATS:
 
 There are independent arrays for byte/data and word/data commands.  Depending
@@ -33,6 +41,9 @@ If the hardware for your driver has banked registers (e.g. Winbond sensors
 chips) this module will not work well - although it could be extended to
 support that pretty easily.
 
+Only one chip address is supported - although this module could be
+extended to support more.
+
 If you spam it hard enough, printk can be lossy.  This module really wants
 something like relayfs.
 

+ 0 - 1
drivers/acorn/char/i2c.c

@@ -308,7 +308,6 @@ static struct i2c_algo_bit_data ioc_data = {
 	.getsda		= ioc_getsda,
 	.getscl		= ioc_getscl,
 	.udelay		= 80,
-	.mdelay		= 80,
 	.timeout	= 100
 };
 

+ 1 - 1
drivers/acpi/i2c_ec.c

@@ -293,7 +293,7 @@ static u32 acpi_ec_smb_func(struct i2c_adapter *adapter)
 		I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC);
 }
 
-static struct i2c_algorithm acpi_ec_smbus_algorithm = {
+static const struct i2c_algorithm acpi_ec_smbus_algorithm = {
 	.smbus_xfer = acpi_ec_smb_access,
 	.functionality = acpi_ec_smb_func,
 };

+ 1 - 0
drivers/hwmon/it87.c

@@ -243,6 +243,7 @@ static struct i2c_driver it87_driver = {
 
 static struct i2c_driver it87_isa_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "it87-isa",
 	},
 	.attach_adapter	= it87_isa_attach_adapter,

+ 1 - 0
drivers/hwmon/lm78.c

@@ -175,6 +175,7 @@ static struct i2c_driver lm78_driver = {
 
 static struct i2c_driver lm78_isa_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "lm78-isa",
 	},
 	.attach_adapter	= lm78_isa_attach_adapter,

+ 1 - 0
drivers/hwmon/pc87360.c

@@ -238,6 +238,7 @@ static struct pc87360_data *pc87360_update_device(struct device *dev);
 
 static struct i2c_driver pc87360_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "pc87360",
 	},
 	.attach_adapter	= pc87360_detect,

+ 1 - 0
drivers/hwmon/sis5595.c

@@ -200,6 +200,7 @@ static void sis5595_init_client(struct i2c_client *client);
 
 static struct i2c_driver sis5595_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "sis5595",
 	},
 	.attach_adapter	= sis5595_detect,

+ 1 - 0
drivers/hwmon/smsc47b397.c

@@ -228,6 +228,7 @@ static int smsc47b397_detect(struct i2c_adapter *adapter);
 
 static struct i2c_driver smsc47b397_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "smsc47b397",
 	},
 	.attach_adapter	= smsc47b397_detect,

+ 1 - 0
drivers/hwmon/smsc47m1.c

@@ -128,6 +128,7 @@ static struct smsc47m1_data *smsc47m1_update_device(struct device *dev,
 
 static struct i2c_driver smsc47m1_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "smsc47m1",
 	},
 	.attach_adapter	= smsc47m1_detect,

+ 1 - 0
drivers/hwmon/via686a.c

@@ -574,6 +574,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
    smbus_driver and isa_driver, and clients could be of either kind */
 static struct i2c_driver via686a_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "via686a",
 	},
 	.attach_adapter	= via686a_detect,

+ 1 - 0
drivers/hwmon/vt8231.c

@@ -587,6 +587,7 @@ static DEVICE_ATTR(alarms, S_IRUGO, show_alarms, NULL);
 
 static struct i2c_driver vt8231_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "vt8231",
 	},
 	.attach_adapter	= vt8231_detect,

+ 1 - 0
drivers/hwmon/w83627ehf.c

@@ -903,6 +903,7 @@ static int w83627ehf_detach_client(struct i2c_client *client)
 
 static struct i2c_driver w83627ehf_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "w83627ehf",
 	},
 	.attach_adapter	= w83627ehf_detect,

+ 1 - 0
drivers/hwmon/w83627hf.c

@@ -339,6 +339,7 @@ static void w83627hf_init_client(struct i2c_client *client);
 
 static struct i2c_driver w83627hf_driver = {
 	.driver = {
+		.owner	= THIS_MODULE,
 		.name	= "w83627hf",
 	},
 	.attach_adapter	= w83627hf_detect,

+ 1 - 0
drivers/hwmon/w83781d.c

@@ -288,6 +288,7 @@ static struct i2c_driver w83781d_driver = {
 
 static struct i2c_driver w83781d_isa_driver = {
 	.driver = {
+		.owner = THIS_MODULE,
 		.name = "w83781d-isa",
 	},
 	.attach_adapter = w83781d_isa_attach_adapter,

+ 1 - 1
drivers/i2c/Kconfig

@@ -1,5 +1,5 @@
 #
-# Character device configuration
+# I2C subsystem configuration
 #
 
 menu "I2C support"

+ 0 - 6
drivers/i2c/algos/Kconfig

@@ -53,12 +53,6 @@ config I2C_ALGO8XX
 	tristate "MPC8xx CPM I2C interface"
 	depends on 8xx && I2C
 
-config I2C_ALGO_SIBYTE
-	tristate "SiByte SMBus interface"
-	depends on SIBYTE_SB1xxx_SOC && I2C
-	help
-	  Supports the SiByte SOC on-chip I2C interfaces (2 channels).
-
 config I2C_ALGO_SGI
 	tristate "I2C SGI interfaces"
 	depends on I2C && (SGI_IP22 || SGI_IP32 || X86_VISWS)

+ 0 - 1
drivers/i2c/algos/Makefile

@@ -6,7 +6,6 @@ obj-$(CONFIG_I2C_ALGOBIT)	+= i2c-algo-bit.o
 obj-$(CONFIG_I2C_ALGOPCF)	+= i2c-algo-pcf.o
 obj-$(CONFIG_I2C_ALGOPCA)	+= i2c-algo-pca.o
 obj-$(CONFIG_I2C_ALGOITE)	+= i2c-algo-ite.o
-obj-$(CONFIG_I2C_ALGO_SIBYTE)	+= i2c-algo-sibyte.o
 obj-$(CONFIG_I2C_ALGO_SGI)	+= i2c-algo-sgi.o
 
 ifeq ($(CONFIG_I2C_DEBUG_ALGO),y)

+ 9 - 14
drivers/i2c/algos/i2c-algo-bit.c

@@ -76,17 +76,15 @@ static inline void scllo(struct i2c_algo_bit_data *adap)
  * Raise scl line, and do checking for delays. This is necessary for slower
  * devices.
  */
-static inline int sclhi(struct i2c_algo_bit_data *adap)
+static int sclhi(struct i2c_algo_bit_data *adap)
 {
 	unsigned long start;
 
 	setscl(adap,1);
 
 	/* Not all adapters have scl sense line... */
-	if (adap->getscl == NULL ) {
-		udelay(adap->udelay);
-		return 0;
-	}
+	if (!adap->getscl)
+		goto done;
 
 	start=jiffies;
 	while (! getscl(adap) ) {	
@@ -101,6 +99,8 @@ static inline int sclhi(struct i2c_algo_bit_data *adap)
 		cond_resched();
 	}
 	DEBSTAT(printk(KERN_DEBUG "needed %ld jiffies\n", jiffies-start));
+
+done:
 	udelay(adap->udelay);
 	return 0;
 } 
@@ -121,7 +121,6 @@ static void i2c_repstart(struct i2c_algo_bit_data *adap)
 	DEBPROTO(printk(" Sr "));
 	setsda(adap,1);
 	sclhi(adap);
-	udelay(adap->udelay);
 	
 	sdalo(adap);
 	scllo(adap);
@@ -306,7 +305,7 @@ bailout:
  * 0 chip did not answer
  * -x transmission error
  */
-static inline int try_address(struct i2c_adapter *i2c_adap,
+static int try_address(struct i2c_adapter *i2c_adap,
 		       unsigned char addr, int retries)
 {
 	struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
@@ -354,15 +353,11 @@ static int sendbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 			return (retval<0)? retval : -EFAULT;
 			        /* got a better one ?? */
 		}
-#if 0
-		/* from asm/delay.h */
-		__delay(adap->mdelay * (loops_per_sec / 1000) );
-#endif
 	}
 	return wrcount;
 }
 
-static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
+static int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
 	int inval;
 	int rdcount=0;   	/* counts bytes read */
@@ -412,7 +407,7 @@ static inline int readbytes(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
  * -x an error occurred (like: -EREMOTEIO if the device did not answer, or
  *	-ETIMEDOUT, for example if the lines are stuck...) 
  */
-static inline int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg) 
+static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
 {
 	unsigned short flags = msg->flags;
 	unsigned short nak_ok = msg->flags & I2C_M_IGNORE_NAK;
@@ -517,7 +512,7 @@ static u32 bit_func(struct i2c_adapter *adap)
 
 /* -----exported algorithm data: -------------------------------------	*/
 
-static struct i2c_algorithm i2c_bit_algo = {
+static const struct i2c_algorithm i2c_bit_algo = {
 	.master_xfer	= bit_xfer,
 	.functionality	= bit_func,
 };

+ 1 - 1
drivers/i2c/algos/i2c-algo-pca.c

@@ -355,7 +355,7 @@ static int pca_init(struct i2c_algo_pca_data *adap)
 	return 0;
 }
 
-static struct i2c_algorithm pca_algo = {
+static const struct i2c_algorithm pca_algo = {
 	.master_xfer	= pca_xfer,
 	.functionality	= pca_func,
 };

+ 1 - 1
drivers/i2c/algos/i2c-algo-pcf.c

@@ -458,7 +458,7 @@ static u32 pcf_func(struct i2c_adapter *adap)
 
 /* -----exported algorithm data: -------------------------------------	*/
 
-static struct i2c_algorithm pcf_algo = {
+static const struct i2c_algorithm pcf_algo = {
 	.master_xfer	= pcf_xfer,
 	.functionality	= pcf_func,
 };

+ 1 - 1
drivers/i2c/algos/i2c-algo-sgi.c

@@ -157,7 +157,7 @@ static u32 sgi_func(struct i2c_adapter *adap)
 	return I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm sgi_algo = {
+static const struct i2c_algorithm sgi_algo = {
 	.master_xfer	= sgi_xfer,
 	.functionality	= sgi_func,
 };

+ 0 - 215
drivers/i2c/algos/i2c-algo-sibyte.c

@@ -1,215 +0,0 @@
-/* ------------------------------------------------------------------------- */
-/* i2c-algo-sibyte.c i2c driver algorithms for bit-shift adapters		     */
-/* ------------------------------------------------------------------------- */
-/*   Copyright (C) 2001,2002,2003 Broadcom Corporation
-     Copyright (C) 1995-2000 Simon G. Vogl
-
-    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.		     */
-/* ------------------------------------------------------------------------- */
-
-/* With some changes from Kyösti Mälkki <kmalkki@cc.hut.fi> and even
-   Frodo Looijaard <frodol@dds.nl>.  */
-
-/* Ported for SiByte SOCs by Broadcom Corporation.  */
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-
-#include <asm/io.h>
-#include <asm/sibyte/sb1250_regs.h>
-#include <asm/sibyte/sb1250_smbus.h>
-
-#include <linux/i2c.h>
-#include <linux/i2c-algo-sibyte.h>
-
-/* ----- global defines ----------------------------------------------- */
-#define SMB_CSR(a,r) ((long)(a->reg_base + r))
-
-/* ----- global variables ---------------------------------------------	*/
-
-/* module parameters:
- */
-static int bit_scan;	/* have a look at what's hanging 'round		*/
-
-
-static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr, 
-                      unsigned short flags, char read_write,
-                      u8 command, int size, union i2c_smbus_data * data)
-{
-	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
-        int data_bytes = 0;
-        int error;
-
-        while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        switch (size) {
-        case I2C_SMBUS_QUICK:
-                csr_out32((V_SMB_ADDR(addr) | (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
-			   V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
-                break;
-        case I2C_SMBUS_BYTE:
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
-				  SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 1;
-                } else {
-                        csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
-				  SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        case I2C_SMBUS_BYTE_DATA:
-                csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
-				  SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 1;
-                } else {
-                        csr_out32(V_SMB_LB(data->byte), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
-				  SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        case I2C_SMBUS_WORD_DATA:
-                csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
-                if (read_write == I2C_SMBUS_READ) {
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
-				  SMB_CSR(adap, R_SMB_START));
-                        data_bytes = 2;
-                } else {
-                        csr_out32(V_SMB_LB(data->word & 0xff), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32(V_SMB_MB(data->word >> 8), SMB_CSR(adap, R_SMB_DATA));
-                        csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
-				  SMB_CSR(adap, R_SMB_START));
-                }
-                break;
-        default:
-                return -1;      /* XXXKW better error code? */
-        }
-
-        while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
-                ;
-
-        error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
-        if (error & M_SMB_ERROR) {
-                /* Clear error bit by writing a 1 */
-                csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
-                return -1;      /* XXXKW better error code? */
-        }
-
-        if (data_bytes == 1)
-                data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
-        if (data_bytes == 2)
-                data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
-
-        return 0;
-}
-
-static int algo_control(struct i2c_adapter *adapter, 
-	unsigned int cmd, unsigned long arg)
-{
-	return 0;
-}
-
-static u32 bit_func(struct i2c_adapter *adap)
-{
-	return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
-                I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
-}
-
-
-/* -----exported algorithm data: -------------------------------------	*/
-
-static struct i2c_algorithm i2c_sibyte_algo = {
-	.smbus_xfer	= smbus_xfer,
-	.algo_control	= algo_control, /* ioctl */
-	.functionality	= bit_func,
-};
-
-/* 
- * registering functions to load algorithms at runtime 
- */
-int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
-{
-	int i;
-	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
-
-	/* register new adapter to i2c module... */
-	i2c_adap->algo = &i2c_sibyte_algo;
-        
-        /* Set the frequency to 100 kHz */
-        csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
-        csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
-
-	/* scan bus */
-	if (bit_scan) {
-                union i2c_smbus_data data;
-                int rc;
-		printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
-		       i2c_adap->name);
-		for (i = 0x00; i < 0x7f; i++) {
-                        /* XXXKW is this a realistic probe? */
-                        rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
-                                        I2C_SMBUS_BYTE_DATA, &data);
-			if (!rc) {
-				printk("(%02x)",i); 
-			} else 
-				printk("."); 
-		}
-		printk("\n");
-	}
-
-	return i2c_add_adapter(i2c_adap);
-}
-
-
-int i2c_sibyte_del_bus(struct i2c_adapter *adap)
-{
-	int res;
-
-	if ((res = i2c_del_adapter(adap)) < 0)
-		return res;
-
-	return 0;
-}
-
-int __init i2c_algo_sibyte_init (void)
-{
-	printk("i2c-algo-sibyte.o: i2c SiByte algorithm module\n");
-	return 0;
-}
-
-
-EXPORT_SYMBOL(i2c_sibyte_add_bus);
-EXPORT_SYMBOL(i2c_sibyte_del_bus);
-
-#ifdef MODULE
-MODULE_AUTHOR("Kip Walker, Broadcom Corp.");
-MODULE_DESCRIPTION("SiByte I2C-Bus algorithm");
-module_param(bit_scan, int, 0);
-MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
-MODULE_LICENSE("GPL");
-
-int init_module(void) 
-{
-	return i2c_algo_sibyte_init();
-}
-
-void cleanup_module(void) 
-{
-}
-#endif

+ 22 - 12
drivers/i2c/busses/Kconfig

@@ -75,11 +75,11 @@ config I2C_AMD8111
 	  will be called i2c-amd8111.
 
 config I2C_AU1550
-	tristate "Au1550 SMBus interface"
-	depends on I2C && SOC_AU1550
+	tristate "Au1550/Au1200 SMBus interface"
+	depends on I2C && (SOC_AU1550 || SOC_AU1200)
 	help
 	  If you say yes to this option, support will be included for the
-	  Au1550 SMBus interface.
+	  Au1550 and Au1200 SMBus interface.
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-au1550.
@@ -287,6 +287,16 @@ config I2C_OCORES
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-ocores.
 
+config I2C_OMAP
+	tristate "OMAP I2C adapter"
+	depends on I2C && ARCH_OMAP
+	default y if MACH_OMAP_H3 || MACH_OMAP_OSK
+	help
+	  If you say yes to this option, support will be included for the
+	  I2C interface on the Texas Instruments OMAP1/2 family of processors.
+	  Like OMAP1510/1610/1710/5912 and OMAP242x.
+	  For details see http://www.ti.com/omap.
+
 config I2C_PARPORT
 	tristate "Parallel port adapter"
 	depends on I2C && PARPORT
@@ -482,19 +492,19 @@ config I2C_VIA
 	  will be called i2c-via.
 
 config I2C_VIAPRO
-	tristate "VIA 82C596/82C686/823x"
+	tristate "VIA 82C596/82C686/82xx"
 	depends on I2C && PCI
 	help
 	  If you say yes to this option, support will be included for the VIA
-	  82C596/82C686/823x I2C interfaces.  Specifically, the following 
+	  82C596/82C686/82xx I2C interfaces.  Specifically, the following
 	  chipsets are supported:
-	  82C596A/B
-	  82C686A/B
-	  8231
-	  8233
-	  8233A
-	  8235
-	  8237
+	    VT82C596A/B
+	    VT82C686A/B
+	    VT8231
+	    VT8233/A
+	    VT8235
+	    VT8237R/A
+	    VT8251
 
 	  This driver can also be built as a module.  If so, the module
 	  will be called i2c-viapro.

+ 1 - 0
drivers/i2c/busses/Makefile

@@ -24,6 +24,7 @@ obj-$(CONFIG_I2C_MPC)		+= i2c-mpc.o
 obj-$(CONFIG_I2C_MV64XXX)	+= i2c-mv64xxx.o
 obj-$(CONFIG_I2C_NFORCE2)	+= i2c-nforce2.o
 obj-$(CONFIG_I2C_OCORES)	+= i2c-ocores.o
+obj-$(CONFIG_I2C_OMAP)		+= i2c-omap.o
 obj-$(CONFIG_I2C_PARPORT)	+= i2c-parport.o
 obj-$(CONFIG_I2C_PARPORT_LIGHT)	+= i2c-parport-light.o
 obj-$(CONFIG_I2C_PCA_ISA)	+= i2c-pca-isa.o

+ 1 - 1
drivers/i2c/busses/i2c-ali1535.c

@@ -468,7 +468,7 @@ static u32 ali1535_func(struct i2c_adapter *adapter)
 	    I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= ali1535_access,
 	.functionality	= ali1535_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-ali1563.c

@@ -367,7 +367,7 @@ static void ali1563_shutdown(struct pci_dev *dev)
 	release_region(ali1563_smba,ALI1563_SMB_IOSIZE);
 }
 
-static struct i2c_algorithm ali1563_algorithm = {
+static const struct i2c_algorithm ali1563_algorithm = {
 	.smbus_xfer	= ali1563_access,
 	.functionality	= ali1563_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-ali15x3.c

@@ -463,7 +463,7 @@ static u32 ali15x3_func(struct i2c_adapter *adapter)
 	    I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= ali15x3_access,
 	.functionality	= ali15x3_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-amd756.c

@@ -294,7 +294,7 @@ static u32 amd756_func(struct i2c_adapter *adapter)
 	    I2C_FUNC_SMBUS_BLOCK_DATA | I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= amd756_access,
 	.functionality	= amd756_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-amd8111.c

@@ -316,7 +316,7 @@ static u32 amd8111_func(struct i2c_adapter *adapter)
 		I2C_FUNC_SMBUS_I2C_BLOCK | I2C_FUNC_SMBUS_HWPEC_CALC;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer = amd8111_access,
 	.functionality = amd8111_func,
 };

+ 13 - 8
drivers/i2c/busses/i2c-au1550.c

@@ -34,8 +34,7 @@
 #include <linux/errno.h>
 #include <linux/i2c.h>
 
-#include <asm/mach-au1x00/au1000.h>
-#include <asm/mach-pb1x00/pb1550.h>
+#include <asm/mach-au1x00/au1xxx.h>
 #include <asm/mach-au1x00/au1xxx_psc.h>
 
 #include "i2c-au1550.h"
@@ -118,13 +117,19 @@ do_address(struct i2c_au1550_data *adap, unsigned int addr, int rd)
 
 	/* Reset the FIFOs, clear events.
 	*/
-	sp->psc_smbpcr = PSC_SMBPCR_DC;
+	stat = sp->psc_smbstat;
 	sp->psc_smbevnt = PSC_SMBEVNT_ALLCLR;
 	au_sync();
-	do {
-		stat = sp->psc_smbpcr;
+
+	if (!(stat & PSC_SMBSTAT_TE) || !(stat & PSC_SMBSTAT_RE)) {
+		sp->psc_smbpcr = PSC_SMBPCR_DC;
 		au_sync();
-	} while ((stat & PSC_SMBPCR_DC) != 0);
+		do {
+			stat = sp->psc_smbpcr;
+			au_sync();
+		} while ((stat & PSC_SMBPCR_DC) != 0);
+		udelay(50);
+	}
 
 	/* Write out the i2c chip address and specify operation
 	*/
@@ -279,10 +284,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 static u32
 au1550_func(struct i2c_adapter *adap)
 {
-	return I2C_FUNC_I2C;
+	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm au1550_algo = {
+static const struct i2c_algorithm au1550_algo = {
 	.master_xfer	= au1550_xfer,
 	.functionality	= au1550_func,
 };

+ 0 - 1
drivers/i2c/busses/i2c-elektor.c

@@ -196,7 +196,6 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
 	.getclock   = pcf_isa_getclock,
 	.waitforpin = pcf_isa_waitforpin,
 	.udelay	    = 10,
-	.mdelay	    = 10,
 	.timeout    = 100,
 };
 

+ 0 - 1
drivers/i2c/busses/i2c-hydra.c

@@ -99,7 +99,6 @@ static struct i2c_algo_bit_data hydra_bit_data = {
 	.getsda		= hydra_bit_getsda,
 	.getscl		= hydra_bit_getscl,
 	.udelay		= 5,
-	.mdelay		= 5,
 	.timeout	= HZ
 };
 

+ 1 - 1
drivers/i2c/busses/i2c-i801.c

@@ -434,7 +434,7 @@ static u32 i801_func(struct i2c_adapter *adapter)
 	     | (isich4 ? I2C_FUNC_SMBUS_HWPEC_CALC : 0);
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= i801_access,
 	.functionality	= i801_func,
 };

+ 0 - 2
drivers/i2c/busses/i2c-i810.c

@@ -166,7 +166,6 @@ static struct i2c_algo_bit_data i810_i2c_bit_data = {
 	.getsda		= bit_i810i2c_getsda,
 	.getscl		= bit_i810i2c_getscl,
 	.udelay		= CYCLE_DELAY,
-	.mdelay		= CYCLE_DELAY,
 	.timeout	= TIMEOUT,
 };
 
@@ -182,7 +181,6 @@ static struct i2c_algo_bit_data i810_ddc_bit_data = {
 	.getsda		= bit_i810ddc_getsda,
 	.getscl		= bit_i810ddc_getscl,
 	.udelay		= CYCLE_DELAY,
-	.mdelay		= CYCLE_DELAY,
 	.timeout	= TIMEOUT,
 };
 

+ 1 - 1
drivers/i2c/busses/i2c-ibm_iic.c

@@ -625,7 +625,7 @@ static u32 iic_func(struct i2c_adapter *adap)
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR;
 }
 
-static struct i2c_algorithm iic_algo = {
+static const struct i2c_algorithm iic_algo = {
 	.master_xfer 	= iic_xfer,
 	.functionality	= iic_func
 };

+ 1 - 1
drivers/i2c/busses/i2c-iop3xx.c

@@ -401,7 +401,7 @@ iop3xx_i2c_func(struct i2c_adapter *adap)
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm iop3xx_i2c_algo = {
+static const struct i2c_algorithm iop3xx_i2c_algo = {
 	.master_xfer	= iop3xx_i2c_master_xfer,
 	.algo_control	= iop3xx_i2c_algo_control,
 	.functionality	= iop3xx_i2c_func,

+ 35 - 7
drivers/i2c/busses/i2c-isa.c

@@ -43,7 +43,7 @@
 static u32 isa_func(struct i2c_adapter *adapter);
 
 /* This is the actual algorithm we define */
-static struct i2c_algorithm isa_algorithm = {
+static const struct i2c_algorithm isa_algorithm = {
 	.functionality	= isa_func,
 };
 
@@ -89,9 +89,14 @@ int i2c_isa_add_driver(struct i2c_driver *driver)
 	dev_dbg(&isa_adapter.dev, "Driver %s registered\n", driver->driver.name);
 
 	/* Now look for clients */
-	driver->attach_adapter(&isa_adapter);
-
-	return 0;
+	res = driver->attach_adapter(&isa_adapter);
+	if (res) {
+		dev_err(&isa_adapter.dev,
+			"Driver %s failed to attach adapter, unregistering\n",
+			driver->driver.name);
+		driver_unregister(&driver->driver);
+	}
+	return res;
 }
 
 int i2c_isa_del_driver(struct i2c_driver *driver)
@@ -125,6 +130,8 @@ int i2c_isa_del_driver(struct i2c_driver *driver)
 
 static int __init i2c_isa_init(void)
 {
+	int err;
+
 	mutex_init(&isa_adapter.clist_lock);
 	INIT_LIST_HEAD(&isa_adapter.clients);
 
@@ -133,8 +140,16 @@ static int __init i2c_isa_init(void)
 	sprintf(isa_adapter.dev.bus_id, "i2c-%d", isa_adapter.nr);
 	isa_adapter.dev.driver = &i2c_adapter_driver;
 	isa_adapter.dev.release = &i2c_adapter_dev_release;
-	device_register(&isa_adapter.dev);
-	device_create_file(&isa_adapter.dev, &dev_attr_name);
+	err = device_register(&isa_adapter.dev);
+	if (err) {
+		printk(KERN_ERR "i2c-isa: Failed to register device\n");
+		goto exit;
+	}
+	err = device_create_file(&isa_adapter.dev, &dev_attr_name);
+	if (err) {
+		printk(KERN_ERR "i2c-isa: Failed to create name file\n");
+		goto exit_unregister;
+	}
 
 	/* Add this adapter to the i2c_adapter class */
 	memset(&isa_adapter.class_dev, 0x00, sizeof(struct class_device));
@@ -142,11 +157,24 @@ static int __init i2c_isa_init(void)
 	isa_adapter.class_dev.class = &i2c_adapter_class;
 	strlcpy(isa_adapter.class_dev.class_id, isa_adapter.dev.bus_id,
 		BUS_ID_SIZE);
-	class_device_register(&isa_adapter.class_dev);
+	err = class_device_register(&isa_adapter.class_dev);
+	if (err) {
+		printk(KERN_ERR "i2c-isa: Failed to register class device\n");
+		goto exit_remove_name;
+	}
 
 	dev_dbg(&isa_adapter.dev, "%s registered\n", isa_adapter.name);
 
 	return 0;
+
+exit_remove_name:
+	device_remove_file(&isa_adapter.dev, &dev_attr_name);
+exit_unregister:
+	init_completion(&isa_adapter.dev_released); /* Needed? */
+	device_unregister(&isa_adapter.dev);
+	wait_for_completion(&isa_adapter.dev_released);
+exit:
+	return err;
 }
 
 static void __exit i2c_isa_exit(void)

+ 0 - 1
drivers/i2c/busses/i2c-ixp2000.c

@@ -114,7 +114,6 @@ static int ixp2000_i2c_probe(struct platform_device *plat_dev)
 	drv_data->algo_data.getsda = ixp2000_bit_getsda;
 	drv_data->algo_data.getscl = ixp2000_bit_getscl;
 	drv_data->algo_data.udelay = 6;
-	drv_data->algo_data.mdelay = 6;
 	drv_data->algo_data.timeout = 100;
 
 	drv_data->adapter.id = I2C_HW_B_IXP2000,

+ 0 - 1
drivers/i2c/busses/i2c-ixp4xx.c

@@ -122,7 +122,6 @@ static int ixp4xx_i2c_probe(struct platform_device *plat_dev)
 	drv_data->algo_data.getsda = ixp4xx_bit_getsda;
 	drv_data->algo_data.getscl = ixp4xx_bit_getscl;
 	drv_data->algo_data.udelay = 10;
-	drv_data->algo_data.mdelay = 10;
 	drv_data->algo_data.timeout = 100;
 
 	drv_data->adapter.id = I2C_HW_B_IXP4XX;

+ 1 - 1
drivers/i2c/busses/i2c-mpc.c

@@ -272,7 +272,7 @@ static u32 mpc_functionality(struct i2c_adapter *adap)
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm mpc_algo = {
+static const struct i2c_algorithm mpc_algo = {
 	.master_xfer = mpc_xfer,
 	.functionality = mpc_functionality,
 };

+ 1 - 1
drivers/i2c/busses/i2c-mv64xxx.c

@@ -431,7 +431,7 @@ mv64xxx_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 	return num;
 }
 
-static struct i2c_algorithm mv64xxx_i2c_algo = {
+static const struct i2c_algorithm mv64xxx_i2c_algo = {
 	.master_xfer = mv64xxx_i2c_xfer,
 	.functionality = mv64xxx_i2c_functionality,
 };

+ 1 - 1
drivers/i2c/busses/i2c-nforce2.c

@@ -109,7 +109,7 @@ static s32 nforce2_access(struct i2c_adapter *adap, u16 addr,
 static u32 nforce2_func(struct i2c_adapter *adapter);
 
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer = nforce2_access,
 	.functionality = nforce2_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-ocores.c

@@ -199,7 +199,7 @@ static u32 ocores_func(struct i2c_adapter *adap)
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm ocores_algorithm = {
+static const struct i2c_algorithm ocores_algorithm = {
 	.master_xfer	= ocores_xfer,
 	.functionality	= ocores_func,
 };

+ 676 - 0
drivers/i2c/busses/i2c-omap.c

@@ -0,0 +1,676 @@
+/*
+ * TI OMAP I2C master mode driver
+ *
+ * Copyright (C) 2003 MontaVista Software, Inc.
+ * Copyright (C) 2004 Texas Instruments.
+ *
+ * Updated to work with multiple I2C interfaces on 24xx by
+ * Tony Lindgren <tony@atomide.com> and Imre Deak <imre.deak@nokia.com>
+ * Copyright (C) 2005 Nokia Corporation
+ *
+ * Cleaned up by Juha Yrjölä <juha.yrjola@nokia.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.
+ */
+
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/i2c.h>
+#include <linux/err.h>
+#include <linux/interrupt.h>
+#include <linux/completion.h>
+#include <linux/platform_device.h>
+#include <linux/clk.h>
+
+#include <asm/io.h>
+
+/* timeout waiting for the controller to respond */
+#define OMAP_I2C_TIMEOUT (msecs_to_jiffies(1000))
+
+#define OMAP_I2C_REV_REG		0x00
+#define OMAP_I2C_IE_REG			0x04
+#define OMAP_I2C_STAT_REG		0x08
+#define OMAP_I2C_IV_REG			0x0c
+#define OMAP_I2C_SYSS_REG		0x10
+#define OMAP_I2C_BUF_REG		0x14
+#define OMAP_I2C_CNT_REG		0x18
+#define OMAP_I2C_DATA_REG		0x1c
+#define OMAP_I2C_SYSC_REG		0x20
+#define OMAP_I2C_CON_REG		0x24
+#define OMAP_I2C_OA_REG			0x28
+#define OMAP_I2C_SA_REG			0x2c
+#define OMAP_I2C_PSC_REG		0x30
+#define OMAP_I2C_SCLL_REG		0x34
+#define OMAP_I2C_SCLH_REG		0x38
+#define OMAP_I2C_SYSTEST_REG		0x3c
+
+/* I2C Interrupt Enable Register (OMAP_I2C_IE): */
+#define OMAP_I2C_IE_XRDY	(1 << 4)	/* TX data ready int enable */
+#define OMAP_I2C_IE_RRDY	(1 << 3)	/* RX data ready int enable */
+#define OMAP_I2C_IE_ARDY	(1 << 2)	/* Access ready int enable */
+#define OMAP_I2C_IE_NACK	(1 << 1)	/* No ack interrupt enable */
+#define OMAP_I2C_IE_AL		(1 << 0)	/* Arbitration lost int ena */
+
+/* I2C Status Register (OMAP_I2C_STAT): */
+#define OMAP_I2C_STAT_SBD	(1 << 15)	/* Single byte data */
+#define OMAP_I2C_STAT_BB	(1 << 12)	/* Bus busy */
+#define OMAP_I2C_STAT_ROVR	(1 << 11)	/* Receive overrun */
+#define OMAP_I2C_STAT_XUDF	(1 << 10)	/* Transmit underflow */
+#define OMAP_I2C_STAT_AAS	(1 << 9)	/* Address as slave */
+#define OMAP_I2C_STAT_AD0	(1 << 8)	/* Address zero */
+#define OMAP_I2C_STAT_XRDY	(1 << 4)	/* Transmit data ready */
+#define OMAP_I2C_STAT_RRDY	(1 << 3)	/* Receive data ready */
+#define OMAP_I2C_STAT_ARDY	(1 << 2)	/* Register access ready */
+#define OMAP_I2C_STAT_NACK	(1 << 1)	/* No ack interrupt enable */
+#define OMAP_I2C_STAT_AL	(1 << 0)	/* Arbitration lost int ena */
+
+/* I2C Buffer Configuration Register (OMAP_I2C_BUF): */
+#define OMAP_I2C_BUF_RDMA_EN	(1 << 15)	/* RX DMA channel enable */
+#define OMAP_I2C_BUF_XDMA_EN	(1 << 7)	/* TX DMA channel enable */
+
+/* I2C Configuration Register (OMAP_I2C_CON): */
+#define OMAP_I2C_CON_EN		(1 << 15)	/* I2C module enable */
+#define OMAP_I2C_CON_BE		(1 << 14)	/* Big endian mode */
+#define OMAP_I2C_CON_STB	(1 << 11)	/* Start byte mode (master) */
+#define OMAP_I2C_CON_MST	(1 << 10)	/* Master/slave mode */
+#define OMAP_I2C_CON_TRX	(1 << 9)	/* TX/RX mode (master only) */
+#define OMAP_I2C_CON_XA		(1 << 8)	/* Expand address */
+#define OMAP_I2C_CON_RM		(1 << 2)	/* Repeat mode (master only) */
+#define OMAP_I2C_CON_STP	(1 << 1)	/* Stop cond (master only) */
+#define OMAP_I2C_CON_STT	(1 << 0)	/* Start condition (master) */
+
+/* I2C System Test Register (OMAP_I2C_SYSTEST): */
+#ifdef DEBUG
+#define OMAP_I2C_SYSTEST_ST_EN		(1 << 15)	/* System test enable */
+#define OMAP_I2C_SYSTEST_FREE		(1 << 14)	/* Free running mode */
+#define OMAP_I2C_SYSTEST_TMODE_MASK	(3 << 12)	/* Test mode select */
+#define OMAP_I2C_SYSTEST_TMODE_SHIFT	(12)		/* Test mode select */
+#define OMAP_I2C_SYSTEST_SCL_I		(1 << 3)	/* SCL line sense in */
+#define OMAP_I2C_SYSTEST_SCL_O		(1 << 2)	/* SCL line drive out */
+#define OMAP_I2C_SYSTEST_SDA_I		(1 << 1)	/* SDA line sense in */
+#define OMAP_I2C_SYSTEST_SDA_O		(1 << 0)	/* SDA line drive out */
+#endif
+
+/* I2C System Status register (OMAP_I2C_SYSS): */
+#define OMAP_I2C_SYSS_RDONE		(1 << 0)	/* Reset Done */
+
+/* I2C System Configuration Register (OMAP_I2C_SYSC): */
+#define OMAP_I2C_SYSC_SRST		(1 << 1)	/* Soft Reset */
+
+/* REVISIT: Use platform_data instead of module parameters */
+/* Fast Mode = 400 kHz, Standard = 100 kHz */
+static int clock = 100; /* Default: 100 kHz */
+module_param(clock, int, 0);
+MODULE_PARM_DESC(clock, "Set I2C clock in kHz: 400=fast mode (default == 100)");
+
+struct omap_i2c_dev {
+	struct device		*dev;
+	void __iomem		*base;		/* virtual */
+	int			irq;
+	struct clk		*iclk;		/* Interface clock */
+	struct clk		*fclk;		/* Functional clock */
+	struct completion	cmd_complete;
+	struct resource		*ioarea;
+	u16			cmd_err;
+	u8			*buf;
+	size_t			buf_len;
+	struct i2c_adapter	adapter;
+	unsigned		rev1:1;
+};
+
+static inline void omap_i2c_write_reg(struct omap_i2c_dev *i2c_dev,
+				      int reg, u16 val)
+{
+	__raw_writew(val, i2c_dev->base + reg);
+}
+
+static inline u16 omap_i2c_read_reg(struct omap_i2c_dev *i2c_dev, int reg)
+{
+	return __raw_readw(i2c_dev->base + reg);
+}
+
+static int omap_i2c_get_clocks(struct omap_i2c_dev *dev)
+{
+	if (cpu_is_omap16xx() || cpu_is_omap24xx()) {
+		dev->iclk = clk_get(dev->dev, "i2c_ick");
+		if (IS_ERR(dev->iclk)) {
+			dev->iclk = NULL;
+			return -ENODEV;
+		}
+	}
+
+	dev->fclk = clk_get(dev->dev, "i2c_fck");
+	if (IS_ERR(dev->fclk)) {
+		if (dev->iclk != NULL) {
+			clk_put(dev->iclk);
+			dev->iclk = NULL;
+		}
+		dev->fclk = NULL;
+		return -ENODEV;
+	}
+
+	return 0;
+}
+
+static void omap_i2c_put_clocks(struct omap_i2c_dev *dev)
+{
+	clk_put(dev->fclk);
+	dev->fclk = NULL;
+	if (dev->iclk != NULL) {
+		clk_put(dev->iclk);
+		dev->iclk = NULL;
+	}
+}
+
+static void omap_i2c_enable_clocks(struct omap_i2c_dev *dev)
+{
+	if (dev->iclk != NULL)
+		clk_enable(dev->iclk);
+	clk_enable(dev->fclk);
+}
+
+static void omap_i2c_disable_clocks(struct omap_i2c_dev *dev)
+{
+	if (dev->iclk != NULL)
+		clk_disable(dev->iclk);
+	clk_disable(dev->fclk);
+}
+
+static int omap_i2c_init(struct omap_i2c_dev *dev)
+{
+	u16 psc = 0;
+	unsigned long fclk_rate = 12000000;
+	unsigned long timeout;
+
+	if (!dev->rev1) {
+		omap_i2c_write_reg(dev, OMAP_I2C_SYSC_REG, OMAP_I2C_SYSC_SRST);
+		/* For some reason we need to set the EN bit before the
+		 * reset done bit gets set. */
+		timeout = jiffies + OMAP_I2C_TIMEOUT;
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+		while (!(omap_i2c_read_reg(dev, OMAP_I2C_SYSS_REG) &
+			 OMAP_I2C_SYSS_RDONE)) {
+			if (time_after(jiffies, timeout)) {
+				dev_warn(dev->dev, "timeout waiting"
+						"for controller reset\n");
+				return -ETIMEDOUT;
+			}
+			msleep(1);
+		}
+	}
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+
+	if (cpu_class_is_omap1()) {
+		struct clk *armxor_ck;
+
+		armxor_ck = clk_get(NULL, "armxor_ck");
+		if (IS_ERR(armxor_ck))
+			dev_warn(dev->dev, "Could not get armxor_ck\n");
+		else {
+			fclk_rate = clk_get_rate(armxor_ck);
+			clk_put(armxor_ck);
+		}
+		/* TRM for 5912 says the I2C clock must be prescaled to be
+		 * between 7 - 12 MHz. The XOR input clock is typically
+		 * 12, 13 or 19.2 MHz. So we should have code that produces:
+		 *
+		 * XOR MHz	Divider		Prescaler
+		 * 12		1		0
+		 * 13		2		1
+		 * 19.2		2		1
+		 */
+		if (fclk_rate > 16000000)
+			psc = (fclk_rate + 8000000) / 12000000;
+	}
+
+	/* Setup clock prescaler to obtain approx 12MHz I2C module clock: */
+	omap_i2c_write_reg(dev, OMAP_I2C_PSC_REG, psc);
+
+	/* Program desired operating rate */
+	fclk_rate /= (psc + 1) * 1000;
+	if (psc > 2)
+		psc = 2;
+
+	omap_i2c_write_reg(dev, OMAP_I2C_SCLL_REG,
+			   fclk_rate / (clock * 2) - 7 + psc);
+	omap_i2c_write_reg(dev, OMAP_I2C_SCLH_REG,
+			   fclk_rate / (clock * 2) - 7 + psc);
+
+	/* Take the I2C module out of reset: */
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_EN);
+
+	/* Enable interrupts */
+	omap_i2c_write_reg(dev, OMAP_I2C_IE_REG,
+			   (OMAP_I2C_IE_XRDY | OMAP_I2C_IE_RRDY |
+			    OMAP_I2C_IE_ARDY | OMAP_I2C_IE_NACK |
+			    OMAP_I2C_IE_AL));
+	return 0;
+}
+
+/*
+ * Waiting on Bus Busy
+ */
+static int omap_i2c_wait_for_bb(struct omap_i2c_dev *dev)
+{
+	unsigned long timeout;
+
+	timeout = jiffies + OMAP_I2C_TIMEOUT;
+	while (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG) & OMAP_I2C_STAT_BB) {
+		if (time_after(jiffies, timeout)) {
+			dev_warn(dev->dev, "timeout waiting for bus ready\n");
+			return -ETIMEDOUT;
+		}
+		msleep(1);
+	}
+
+	return 0;
+}
+
+/*
+ * Low level master read/write transaction.
+ */
+static int omap_i2c_xfer_msg(struct i2c_adapter *adap,
+			     struct i2c_msg *msg, int stop)
+{
+	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+	int r;
+	u16 w;
+
+	dev_dbg(dev->dev, "addr: 0x%04x, len: %d, flags: 0x%x, stop: %d\n",
+		msg->addr, msg->len, msg->flags, stop);
+
+	if (msg->len == 0)
+		return -EINVAL;
+
+	omap_i2c_write_reg(dev, OMAP_I2C_SA_REG, msg->addr);
+
+	/* REVISIT: Could the STB bit of I2C_CON be used with probing? */
+	dev->buf = msg->buf;
+	dev->buf_len = msg->len;
+
+	omap_i2c_write_reg(dev, OMAP_I2C_CNT_REG, dev->buf_len);
+
+	init_completion(&dev->cmd_complete);
+	dev->cmd_err = 0;
+
+	w = OMAP_I2C_CON_EN | OMAP_I2C_CON_MST | OMAP_I2C_CON_STT;
+	if (msg->flags & I2C_M_TEN)
+		w |= OMAP_I2C_CON_XA;
+	if (!(msg->flags & I2C_M_RD))
+		w |= OMAP_I2C_CON_TRX;
+	if (stop)
+		w |= OMAP_I2C_CON_STP;
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+
+	r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
+						      OMAP_I2C_TIMEOUT);
+	dev->buf_len = 0;
+	if (r < 0)
+		return r;
+	if (r == 0) {
+		dev_err(dev->dev, "controller timed out\n");
+		omap_i2c_init(dev);
+		return -ETIMEDOUT;
+	}
+
+	if (likely(!dev->cmd_err))
+		return 0;
+
+	/* We have an error */
+	if (dev->cmd_err & (OMAP_I2C_STAT_AL | OMAP_I2C_STAT_ROVR |
+			    OMAP_I2C_STAT_XUDF)) {
+		omap_i2c_init(dev);
+		return -EIO;
+	}
+
+	if (dev->cmd_err & OMAP_I2C_STAT_NACK) {
+		if (msg->flags & I2C_M_IGNORE_NAK)
+			return 0;
+		if (stop) {
+			w = omap_i2c_read_reg(dev, OMAP_I2C_CON_REG);
+			w |= OMAP_I2C_CON_STP;
+			omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, w);
+		}
+		return -EREMOTEIO;
+	}
+	return -EIO;
+}
+
+
+/*
+ * Prepare controller for a transaction and call omap_i2c_xfer_msg
+ * to do the work during IRQ processing.
+ */
+static int
+omap_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
+{
+	struct omap_i2c_dev *dev = i2c_get_adapdata(adap);
+	int i;
+	int r;
+
+	omap_i2c_enable_clocks(dev);
+
+	/* REVISIT: initialize and use adap->retries. This is an optional
+	 * feature */
+	if ((r = omap_i2c_wait_for_bb(dev)) < 0)
+		goto out;
+
+	for (i = 0; i < num; i++) {
+		r = omap_i2c_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+		if (r != 0)
+			break;
+	}
+
+	if (r == 0)
+		r = num;
+out:
+	omap_i2c_disable_clocks(dev);
+	return r;
+}
+
+static u32
+omap_i2c_func(struct i2c_adapter *adap)
+{
+	return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+static inline void
+omap_i2c_complete_cmd(struct omap_i2c_dev *dev, u16 err)
+{
+	dev->cmd_err |= err;
+	complete(&dev->cmd_complete);
+}
+
+static inline void
+omap_i2c_ack_stat(struct omap_i2c_dev *dev, u16 stat)
+{
+	omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+}
+
+static irqreturn_t
+omap_i2c_rev1_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+	struct omap_i2c_dev *dev = dev_id;
+	u16 iv, w;
+
+	iv = omap_i2c_read_reg(dev, OMAP_I2C_IV_REG);
+	switch (iv) {
+	case 0x00:	/* None */
+		break;
+	case 0x01:	/* Arbitration lost */
+		dev_err(dev->dev, "Arbitration lost\n");
+		omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+		break;
+	case 0x02:	/* No acknowledgement */
+		omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+		omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, OMAP_I2C_CON_STP);
+		break;
+	case 0x03:	/* Register access ready */
+		omap_i2c_complete_cmd(dev, 0);
+		break;
+	case 0x04:	/* Receive data ready */
+		if (dev->buf_len) {
+			w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+			*dev->buf++ = w;
+			dev->buf_len--;
+			if (dev->buf_len) {
+				*dev->buf++ = w >> 8;
+				dev->buf_len--;
+			}
+		} else
+			dev_err(dev->dev, "RRDY IRQ while no data requested\n");
+		break;
+	case 0x05:	/* Transmit data ready */
+		if (dev->buf_len) {
+			w = *dev->buf++;
+			dev->buf_len--;
+			if (dev->buf_len) {
+				w |= *dev->buf++ << 8;
+				dev->buf_len--;
+			}
+			omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+		} else
+			dev_err(dev->dev, "XRDY IRQ while no data to send\n");
+		break;
+	default:
+		return IRQ_NONE;
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t
+omap_i2c_isr(int this_irq, void *dev_id, struct pt_regs *regs)
+{
+	struct omap_i2c_dev *dev = dev_id;
+	u16 bits;
+	u16 stat, w;
+	int count = 0;
+
+	bits = omap_i2c_read_reg(dev, OMAP_I2C_IE_REG);
+	while ((stat = (omap_i2c_read_reg(dev, OMAP_I2C_STAT_REG))) & bits) {
+		dev_dbg(dev->dev, "IRQ (ISR = 0x%04x)\n", stat);
+		if (count++ == 100) {
+			dev_warn(dev->dev, "Too much work in one IRQ\n");
+			break;
+		}
+
+		omap_i2c_write_reg(dev, OMAP_I2C_STAT_REG, stat);
+
+		if (stat & OMAP_I2C_STAT_ARDY) {
+			omap_i2c_complete_cmd(dev, 0);
+			continue;
+		}
+		if (stat & OMAP_I2C_STAT_RRDY) {
+			w = omap_i2c_read_reg(dev, OMAP_I2C_DATA_REG);
+			if (dev->buf_len) {
+				*dev->buf++ = w;
+				dev->buf_len--;
+				if (dev->buf_len) {
+					*dev->buf++ = w >> 8;
+					dev->buf_len--;
+				}
+			} else
+				dev_err(dev->dev, "RRDY IRQ while no data"
+						"requested\n");
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_RRDY);
+			continue;
+		}
+		if (stat & OMAP_I2C_STAT_XRDY) {
+			w = 0;
+			if (dev->buf_len) {
+				w = *dev->buf++;
+				dev->buf_len--;
+				if (dev->buf_len) {
+					w |= *dev->buf++ << 8;
+					dev->buf_len--;
+				}
+			} else
+				dev_err(dev->dev, "XRDY IRQ while no"
+					"data to send\n");
+			omap_i2c_write_reg(dev, OMAP_I2C_DATA_REG, w);
+			omap_i2c_ack_stat(dev, OMAP_I2C_STAT_XRDY);
+			continue;
+		}
+		if (stat & OMAP_I2C_STAT_ROVR) {
+			dev_err(dev->dev, "Receive overrun\n");
+			dev->cmd_err |= OMAP_I2C_STAT_ROVR;
+		}
+		if (stat & OMAP_I2C_STAT_XUDF) {
+			dev_err(dev->dev, "Transmit overflow\n");
+			dev->cmd_err |= OMAP_I2C_STAT_XUDF;
+		}
+		if (stat & OMAP_I2C_STAT_NACK) {
+			omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_NACK);
+			omap_i2c_write_reg(dev, OMAP_I2C_CON_REG,
+					   OMAP_I2C_CON_STP);
+		}
+		if (stat & OMAP_I2C_STAT_AL) {
+			dev_err(dev->dev, "Arbitration lost\n");
+			omap_i2c_complete_cmd(dev, OMAP_I2C_STAT_AL);
+		}
+	}
+
+	return count ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static const struct i2c_algorithm omap_i2c_algo = {
+	.master_xfer	= omap_i2c_xfer,
+	.functionality	= omap_i2c_func,
+};
+
+static int
+omap_i2c_probe(struct platform_device *pdev)
+{
+	struct omap_i2c_dev	*dev;
+	struct i2c_adapter	*adap;
+	struct resource		*mem, *irq, *ioarea;
+	int r;
+
+	/* NOTE: driver uses the static register mapping */
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	if (!mem) {
+		dev_err(&pdev->dev, "no mem resource?\n");
+		return -ENODEV;
+	}
+	irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
+	if (!irq) {
+		dev_err(&pdev->dev, "no irq resource?\n");
+		return -ENODEV;
+	}
+
+	ioarea = request_mem_region(mem->start, (mem->end - mem->start) + 1,
+			pdev->name);
+	if (!ioarea) {
+		dev_err(&pdev->dev, "I2C region already claimed\n");
+		return -EBUSY;
+	}
+
+	if (clock > 200)
+		clock = 400;	/* Fast mode */
+	else
+		clock = 100;	/* Standard mode */
+
+	dev = kzalloc(sizeof(struct omap_i2c_dev), GFP_KERNEL);
+	if (!dev) {
+		r = -ENOMEM;
+		goto err_release_region;
+	}
+
+	dev->dev = &pdev->dev;
+	dev->irq = irq->start;
+	dev->base = (void __iomem *) IO_ADDRESS(mem->start);
+	platform_set_drvdata(pdev, dev);
+
+	if ((r = omap_i2c_get_clocks(dev)) != 0)
+		goto err_free_mem;
+
+	omap_i2c_enable_clocks(dev);
+
+	if (cpu_is_omap15xx())
+		dev->rev1 = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) < 0x20;
+
+	/* reset ASAP, clearing any IRQs */
+	omap_i2c_init(dev);
+
+	r = request_irq(dev->irq, dev->rev1 ? omap_i2c_rev1_isr : omap_i2c_isr,
+			0, pdev->name, dev);
+
+	if (r) {
+		dev_err(dev->dev, "failure requesting irq %i\n", dev->irq);
+		goto err_unuse_clocks;
+	}
+	r = omap_i2c_read_reg(dev, OMAP_I2C_REV_REG) & 0xff;
+	dev_info(dev->dev, "bus %d rev%d.%d at %d kHz\n",
+		 pdev->id, r >> 4, r & 0xf, clock);
+
+	adap = &dev->adapter;
+	i2c_set_adapdata(adap, dev);
+	adap->owner = THIS_MODULE;
+	adap->class = I2C_CLASS_HWMON;
+	strncpy(adap->name, "OMAP I2C adapter", sizeof(adap->name));
+	adap->algo = &omap_i2c_algo;
+	adap->dev.parent = &pdev->dev;
+
+	/* i2c device drivers may be active on return from add_adapter() */
+	r = i2c_add_adapter(adap);
+	if (r) {
+		dev_err(dev->dev, "failure adding adapter\n");
+		goto err_free_irq;
+	}
+
+	omap_i2c_disable_clocks(dev);
+
+	return 0;
+
+err_free_irq:
+	free_irq(dev->irq, dev);
+err_unuse_clocks:
+	omap_i2c_disable_clocks(dev);
+	omap_i2c_put_clocks(dev);
+err_free_mem:
+	platform_set_drvdata(pdev, NULL);
+	kfree(dev);
+err_release_region:
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+
+	return r;
+}
+
+static int
+omap_i2c_remove(struct platform_device *pdev)
+{
+	struct omap_i2c_dev	*dev = platform_get_drvdata(pdev);
+	struct resource		*mem;
+
+	platform_set_drvdata(pdev, NULL);
+
+	free_irq(dev->irq, dev);
+	i2c_del_adapter(&dev->adapter);
+	omap_i2c_write_reg(dev, OMAP_I2C_CON_REG, 0);
+	omap_i2c_put_clocks(dev);
+	kfree(dev);
+	mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
+	release_mem_region(mem->start, (mem->end - mem->start) + 1);
+	return 0;
+}
+
+static struct platform_driver omap_i2c_driver = {
+	.probe		= omap_i2c_probe,
+	.remove		= omap_i2c_remove,
+	.driver		= {
+		.name	= "i2c_omap",
+		.owner	= THIS_MODULE,
+	},
+};
+
+/* I2C may be needed to bring up other drivers */
+static int __init
+omap_i2c_init_driver(void)
+{
+	return platform_driver_register(&omap_i2c_driver);
+}
+subsys_initcall(omap_i2c_init_driver);
+
+static void __exit omap_i2c_exit_driver(void)
+{
+	platform_driver_unregister(&omap_i2c_driver);
+}
+module_exit(omap_i2c_exit_driver);
+
+MODULE_AUTHOR("MontaVista Software, Inc. (and others)");
+MODULE_DESCRIPTION("TI OMAP I2C bus adapter");
+MODULE_LICENSE("GPL");

+ 0 - 1
drivers/i2c/busses/i2c-parport-light.c

@@ -103,7 +103,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
 	.getsda		= parport_getsda,
 	.getscl		= parport_getscl,
 	.udelay		= 50,
-	.mdelay		= 50,
 	.timeout	= HZ,
 }; 
 

+ 0 - 1
drivers/i2c/busses/i2c-parport.c

@@ -138,7 +138,6 @@ static struct i2c_algo_bit_data parport_algo_data = {
 	.getsda		= parport_getsda,
 	.getscl		= parport_getscl,
 	.udelay		= 60,
-	.mdelay		= 60,
 	.timeout	= HZ,
 }; 
 

+ 1 - 1
drivers/i2c/busses/i2c-piix4.c

@@ -376,7 +376,7 @@ static u32 piix4_func(struct i2c_adapter *adapter)
 	    I2C_FUNC_SMBUS_BLOCK_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= piix4_access,
 	.functionality	= piix4_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-powermac.c

@@ -175,7 +175,7 @@ static u32 i2c_powermac_func(struct i2c_adapter * adapter)
 }
 
 /* For now, we only handle smbus */
-static struct i2c_algorithm i2c_powermac_algorithm = {
+static const struct i2c_algorithm i2c_powermac_algorithm = {
 	.smbus_xfer	= i2c_powermac_smbus_xfer,
 	.master_xfer	= i2c_powermac_master_xfer,
 	.functionality	= i2c_powermac_func,

+ 0 - 1
drivers/i2c/busses/i2c-prosavage.c

@@ -180,7 +180,6 @@ static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iom
 	p->algo.getsda	  = bit_s3via_getsda;
 	p->algo.getscl	  = bit_s3via_getscl;
 	p->algo.udelay	  = CYCLE_DELAY;
-	p->algo.mdelay	  = CYCLE_DELAY;
 	p->algo.timeout	  = TIMEOUT;
 	p->algo.data	  = p;
 	p->mmvga	  = mmvga;

+ 1 - 1
drivers/i2c/busses/i2c-pxa.c

@@ -926,7 +926,7 @@ static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
 	return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
 }
 
-static struct i2c_algorithm i2c_pxa_algorithm = {
+static const struct i2c_algorithm i2c_pxa_algorithm = {
 	.master_xfer	= i2c_pxa_xfer,
 	.functionality	= i2c_pxa_functionality,
 };

+ 1 - 1
drivers/i2c/busses/i2c-s3c2410.c

@@ -566,7 +566,7 @@ static u32 s3c24xx_i2c_func(struct i2c_adapter *adap)
 
 /* i2c bus registration info */
 
-static struct i2c_algorithm s3c24xx_i2c_algorithm = {
+static const struct i2c_algorithm s3c24xx_i2c_algorithm = {
 	.master_xfer		= s3c24xx_i2c_xfer,
 	.functionality		= s3c24xx_i2c_func,
 };

+ 0 - 1
drivers/i2c/busses/i2c-savage4.c

@@ -140,7 +140,6 @@ static struct i2c_algo_bit_data sav_i2c_bit_data = {
 	.getsda		= bit_savi2c_getsda,
 	.getscl		= bit_savi2c_getscl,
 	.udelay		= CYCLE_DELAY,
-	.mdelay		= CYCLE_DELAY,
 	.timeout	= TIMEOUT
 };
 

+ 156 - 4
drivers/i2c/busses/i2c-sibyte.c

@@ -1,6 +1,7 @@
 /*
  * Copyright (C) 2004 Steven J. Hill
  * Copyright (C) 2001,2002,2003 Broadcom Corporation
+ * Copyright (C) 1995-2000 Simon G. Vogl
  *
  * This program is free software; you can redistribute it and/or
  * modify it under the terms of the GNU General Public License
@@ -17,11 +18,162 @@
  * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  */
 
+#include <linux/kernel.h>
 #include <linux/module.h>
-#include <linux/i2c-algo-sibyte.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <asm/io.h>
 #include <asm/sibyte/sb1250_regs.h>
 #include <asm/sibyte/sb1250_smbus.h>
 
+
+struct i2c_algo_sibyte_data {
+	void *data;		/* private data */
+	int   bus;		/* which bus */
+	void *reg_base;		/* CSR base */
+};
+
+/* ----- global defines ----------------------------------------------- */
+#define SMB_CSR(a,r) ((long)(a->reg_base + r))
+
+/* ----- global variables --------------------------------------------- */
+
+/* module parameters:
+ */
+static int bit_scan;	/* have a look at what's hanging 'round */
+module_param(bit_scan, int, 0);
+MODULE_PARM_DESC(bit_scan, "Scan for active chips on the bus");
+
+
+static int smbus_xfer(struct i2c_adapter *i2c_adap, u16 addr,
+		      unsigned short flags, char read_write,
+		      u8 command, int size, union i2c_smbus_data * data)
+{
+	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+	int data_bytes = 0;
+	int error;
+
+	while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+		;
+
+	switch (size) {
+	case I2C_SMBUS_QUICK:
+		csr_out32((V_SMB_ADDR(addr) |
+			   (read_write == I2C_SMBUS_READ ? M_SMB_QDATA : 0) |
+			   V_SMB_TT_QUICKCMD), SMB_CSR(adap, R_SMB_START));
+		break;
+	case I2C_SMBUS_BYTE:
+		if (read_write == I2C_SMBUS_READ) {
+			csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_RD1BYTE),
+				  SMB_CSR(adap, R_SMB_START));
+			data_bytes = 1;
+		} else {
+			csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+			csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR1BYTE),
+				  SMB_CSR(adap, R_SMB_START));
+		}
+		break;
+	case I2C_SMBUS_BYTE_DATA:
+		csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+		if (read_write == I2C_SMBUS_READ) {
+			csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD1BYTE),
+				  SMB_CSR(adap, R_SMB_START));
+			data_bytes = 1;
+		} else {
+			csr_out32(V_SMB_LB(data->byte),
+				  SMB_CSR(adap, R_SMB_DATA));
+			csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+				  SMB_CSR(adap, R_SMB_START));
+		}
+		break;
+	case I2C_SMBUS_WORD_DATA:
+		csr_out32(V_SMB_CMD(command), SMB_CSR(adap, R_SMB_CMD));
+		if (read_write == I2C_SMBUS_READ) {
+			csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_CMD_RD2BYTE),
+				  SMB_CSR(adap, R_SMB_START));
+			data_bytes = 2;
+		} else {
+			csr_out32(V_SMB_LB(data->word & 0xff),
+				  SMB_CSR(adap, R_SMB_DATA));
+			csr_out32(V_SMB_MB(data->word >> 8),
+				  SMB_CSR(adap, R_SMB_DATA));
+			csr_out32((V_SMB_ADDR(addr) | V_SMB_TT_WR2BYTE),
+				  SMB_CSR(adap, R_SMB_START));
+		}
+		break;
+	default:
+		return -1;      /* XXXKW better error code? */
+	}
+
+	while (csr_in32(SMB_CSR(adap, R_SMB_STATUS)) & M_SMB_BUSY)
+		;
+
+	error = csr_in32(SMB_CSR(adap, R_SMB_STATUS));
+	if (error & M_SMB_ERROR) {
+		/* Clear error bit by writing a 1 */
+		csr_out32(M_SMB_ERROR, SMB_CSR(adap, R_SMB_STATUS));
+		return -1;      /* XXXKW better error code? */
+	}
+
+	if (data_bytes == 1)
+		data->byte = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xff;
+	if (data_bytes == 2)
+		data->word = csr_in32(SMB_CSR(adap, R_SMB_DATA)) & 0xffff;
+
+	return 0;
+}
+
+static u32 bit_func(struct i2c_adapter *adap)
+{
+	return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA);
+}
+
+
+/* -----exported algorithm data: -------------------------------------	*/
+
+static const struct i2c_algorithm i2c_sibyte_algo = {
+	.smbus_xfer	= smbus_xfer,
+	.functionality	= bit_func,
+};
+
+/*
+ * registering functions to load algorithms at runtime
+ */
+int i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
+{
+	int i;
+	struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
+
+	/* register new adapter to i2c module... */
+	i2c_adap->algo = &i2c_sibyte_algo;
+
+	/* Set the frequency to 100 kHz */
+	csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
+	csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
+
+	/* scan bus */
+	if (bit_scan) {
+		union i2c_smbus_data data;
+		int rc;
+		printk(KERN_INFO " i2c-algo-sibyte.o: scanning bus %s.\n",
+		       i2c_adap->name);
+		for (i = 0x00; i < 0x7f; i++) {
+			/* XXXKW is this a realistic probe? */
+			rc = smbus_xfer(i2c_adap, i, 0, I2C_SMBUS_READ, 0,
+					I2C_SMBUS_BYTE_DATA, &data);
+			if (!rc) {
+				printk("(%02x)",i);
+			} else
+				printk(".");
+		}
+		printk("\n");
+	}
+
+	return i2c_add_adapter(i2c_adap);
+}
+
+
 static struct i2c_algo_sibyte_data sibyte_board_data[2] = {
 	{ NULL, 0, (void *) (CKSEG1+A_SMB_BASE(0)) },
 	{ NULL, 1, (void *) (CKSEG1+A_SMB_BASE(1)) }
@@ -58,13 +210,13 @@ static int __init i2c_sibyte_init(void)
 
 static void __exit i2c_sibyte_exit(void)
 {
-	i2c_sibyte_del_bus(&sibyte_board_adapter[0]);
-	i2c_sibyte_del_bus(&sibyte_board_adapter[1]);
+	i2c_del_bus(&sibyte_board_adapter[0]);
+	i2c_del_bus(&sibyte_board_adapter[1]);
 }
 
 module_init(i2c_sibyte_init);
 module_exit(i2c_sibyte_exit);
 
-MODULE_AUTHOR("Kip Walker <kwalker@broadcom.com>, Steven J. Hill <sjhill@realitydiluted.com>");
+MODULE_AUTHOR("Kip Walker (Broadcom Corp.), Steven J. Hill <sjhill@realitydiluted.com>");
 MODULE_DESCRIPTION("SMBus adapter routines for SiByte boards");
 MODULE_LICENSE("GPL");

+ 1 - 1
drivers/i2c/busses/i2c-sis5595.c

@@ -358,7 +358,7 @@ static u32 sis5595_func(struct i2c_adapter *adapter)
 	    I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= sis5595_access,
 	.functionality	= sis5595_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-sis630.c

@@ -450,7 +450,7 @@ exit:
 }
 
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= sis630_access,
 	.functionality	= sis630_func,
 };

+ 1 - 1
drivers/i2c/busses/i2c-sis96x.c

@@ -242,7 +242,7 @@ static u32 sis96x_func(struct i2c_adapter *adapter)
 	    I2C_FUNC_SMBUS_PROC_CALL;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= sis96x_access,
 	.functionality	= sis96x_func,
 };

+ 19 - 2
drivers/i2c/busses/i2c-stub.c

@@ -27,6 +27,10 @@
 #include <linux/errno.h>
 #include <linux/i2c.h>
 
+static unsigned short chip_addr;
+module_param(chip_addr, ushort, S_IRUGO);
+MODULE_PARM_DESC(chip_addr, "Chip address (between 0x03 and 0x77)\n");
+
 static u8  stub_pointer;
 static u8  stub_bytes[256];
 static u16 stub_words[256];
@@ -37,6 +41,9 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
 {
 	s32 ret;
 
+	if (addr != chip_addr)
+		return -ENODEV;
+
 	switch (size) {
 
 	case I2C_SMBUS_QUICK:
@@ -108,7 +115,7 @@ static u32 stub_func(struct i2c_adapter *adapter)
 		I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.functionality	= stub_func,
 	.smbus_xfer	= stub_xfer,
 };
@@ -122,7 +129,17 @@ static struct i2c_adapter stub_adapter = {
 
 static int __init i2c_stub_init(void)
 {
-	printk(KERN_INFO "i2c-stub loaded\n");
+	if (!chip_addr) {
+		printk(KERN_ERR "i2c-stub: Please specify a chip address\n");
+		return -ENODEV;
+	}
+	if (chip_addr < 0x03 || chip_addr > 0x77) {
+		printk(KERN_ERR "i2c-stub: Invalid chip address 0x%02x\n",
+		       chip_addr);
+		return -EINVAL;
+	}
+
+	printk(KERN_INFO "i2c-stub: Virtual chip at 0x%02x\n", chip_addr);
 	return i2c_add_adapter(&stub_adapter);
 }
 

+ 0 - 1
drivers/i2c/busses/i2c-via.c

@@ -81,7 +81,6 @@ static struct i2c_algo_bit_data bit_data = {
 	.getsda		= bit_via_getsda,
 	.getscl		= bit_via_getscl,
 	.udelay		= 5,
-	.mdelay		= 5,
 	.timeout	= HZ
 };
 

+ 9 - 1
drivers/i2c/busses/i2c-viapro.c

@@ -34,6 +34,8 @@
    VT8233A            0x3147             yes?
    VT8235             0x3177             yes
    VT8237R            0x3227             yes
+   VT8237A            0x3337             yes
+   VT8251             0x3287             yes
 
    Note: we assume there can only be one device, with one SMBus interface.
 */
@@ -297,7 +299,7 @@ static u32 vt596_func(struct i2c_adapter *adapter)
 	return func;
 }
 
-static struct i2c_algorithm smbus_algorithm = {
+static const struct i2c_algorithm smbus_algorithm = {
 	.smbus_xfer	= vt596_access,
 	.functionality	= vt596_func,
 };
@@ -381,7 +383,9 @@ found:
 	dev_dbg(&pdev->dev, "VT596_smba = 0x%X\n", vt596_smba);
 
 	switch (pdev->device) {
+	case PCI_DEVICE_ID_VIA_8251:
 	case PCI_DEVICE_ID_VIA_8237:
+	case PCI_DEVICE_ID_VIA_8237A:
 	case PCI_DEVICE_ID_VIA_8235:
 	case PCI_DEVICE_ID_VIA_8233A:
 	case PCI_DEVICE_ID_VIA_8233_0:
@@ -432,8 +436,12 @@ static struct pci_device_id vt596_ids[] = {
 	  .driver_data = SMBBA3 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237),
 	  .driver_data = SMBBA3 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8237A),
+	  .driver_data = SMBBA3 },
 	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8231_4),
 	  .driver_data = SMBBA1 },
+	{ PCI_DEVICE(PCI_VENDOR_ID_VIA, PCI_DEVICE_ID_VIA_8251),
+	  .driver_data = SMBBA3 },
 	{ 0, }
 };
 

+ 0 - 2
drivers/i2c/busses/i2c-voodoo3.c

@@ -160,7 +160,6 @@ static struct i2c_algo_bit_data voo_i2c_bit_data = {
 	.getsda		= bit_vooi2c_getsda,
 	.getscl		= bit_vooi2c_getscl,
 	.udelay		= CYCLE_DELAY,
-	.mdelay		= CYCLE_DELAY,
 	.timeout	= TIMEOUT
 };
 
@@ -177,7 +176,6 @@ static struct i2c_algo_bit_data voo_ddc_bit_data = {
 	.getsda		= bit_vooddc_getsda,
 	.getscl		= bit_vooddc_getscl,
 	.udelay		= CYCLE_DELAY,
-	.mdelay		= CYCLE_DELAY,
 	.timeout	= TIMEOUT
 };
 

+ 1 - 1
drivers/i2c/busses/scx200_acb.c

@@ -383,7 +383,7 @@ static u32 scx200_acb_func(struct i2c_adapter *adapter)
 }
 
 /* For now, we only handle combined mode (smbus) */
-static struct i2c_algorithm scx200_acb_algorithm = {
+static const struct i2c_algorithm scx200_acb_algorithm = {
 	.smbus_xfer	= scx200_acb_smbus_xfer,
 	.functionality	= scx200_acb_func,
 };

+ 6 - 6
drivers/i2c/busses/scx200_i2c.c

@@ -71,12 +71,12 @@ static int scx200_i2c_getsda(void *data)
  */
 
 static struct i2c_algo_bit_data scx200_i2c_data = {
-	NULL,
-	scx200_i2c_setsda,
-	scx200_i2c_setscl,
-	scx200_i2c_getsda,
-	scx200_i2c_getscl,
-	10, 10, 100,		/* waits, timeout */
+	.setsda		= scx200_i2c_setsda,
+	.setscl		= scx200_i2c_setscl,
+	.getsda		= scx200_i2c_getsda,
+	.getscl		= scx200_i2c_getscl,
+	.udelay		= 10,
+	.timeout	= 100,
 };
 
 static struct i2c_adapter scx200_i2c_ops = {

+ 7 - 1
drivers/i2c/chips/eeprom.c

@@ -209,10 +209,14 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
 	}
 
 	/* create the sysfs eeprom file */
-	sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+	err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+	if (err)
+		goto exit_detach;
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_kfree:
 	kfree(data);
 exit:
@@ -223,6 +227,8 @@ static int eeprom_detach_client(struct i2c_client *client)
 {
 	int err;
 
+	sysfs_remove_bin_file(&client->dev.kobj, &eeprom_attr);
+
 	err = i2c_detach_client(client);
 	if (err)
 		return err;

+ 19 - 6
drivers/i2c/chips/max6875.c

@@ -199,8 +199,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
 	mutex_init(&data->update_lock);
 
 	/* Init fake client data */
-	/* set the client data to the i2c_client so that it will get freed */
-	i2c_set_clientdata(fake_client, fake_client);
+	i2c_set_clientdata(fake_client, NULL);
 	fake_client->addr = address | 1;
 	fake_client->adapter = adapter;
 	fake_client->driver = &max6875_driver;
@@ -214,13 +213,17 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
 		goto exit_kfree2;
 
 	if ((err = i2c_attach_client(fake_client)) != 0)
-		goto exit_detach;
+		goto exit_detach1;
 
-	sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+	err = sysfs_create_bin_file(&real_client->dev.kobj, &user_eeprom_attr);
+	if (err)
+		goto exit_detach2;
 
 	return 0;
 
-exit_detach:
+exit_detach2:
+	i2c_detach_client(fake_client);
+exit_detach1:
 	i2c_detach_client(real_client);
 exit_kfree2:
 	kfree(fake_client);
@@ -229,14 +232,24 @@ exit_kfree1:
 	return err;
 }
 
+/* Will be called for both the real client and the fake client */
 static int max6875_detach_client(struct i2c_client *client)
 {
 	int err;
+	struct max6875_data *data = i2c_get_clientdata(client);
+
+	/* data is NULL for the fake client */
+	if (data)
+		sysfs_remove_bin_file(&client->dev.kobj, &user_eeprom_attr);
 
 	err = i2c_detach_client(client);
 	if (err)
 		return err;
-	kfree(i2c_get_clientdata(client));
+
+	if (data)		/* real client */
+		kfree(data);
+	else			/* fake client */
+		kfree(client);
 	return 0;
 }
 

+ 9 - 2
drivers/i2c/chips/pca9539.c

@@ -148,11 +148,16 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
 	if ((err = i2c_attach_client(new_client)))
 		goto exit_kfree;
 
-	/* Register sysfs hooks (don't care about failure) */
-	sysfs_create_group(&new_client->dev.kobj, &pca9539_defattr_group);
+	/* Register sysfs hooks */
+	err = sysfs_create_group(&new_client->dev.kobj,
+				 &pca9539_defattr_group);
+	if (err)
+		goto exit_detach;
 
 	return 0;
 
+exit_detach:
+	i2c_detach_client(new_client);
 exit_kfree:
 	kfree(data);
 exit:
@@ -163,6 +168,8 @@ static int pca9539_detach_client(struct i2c_client *client)
 {
 	int err;
 
+	sysfs_remove_group(&client->dev.kobj, &pca9539_defattr_group);
+
 	if ((err = i2c_detach_client(client)))
 		return err;
 

+ 17 - 5
drivers/i2c/chips/pcf8574.c

@@ -105,6 +105,16 @@ static ssize_t set_write(struct device *dev, struct device_attribute *attr, cons
 
 static DEVICE_ATTR(write, S_IWUSR | S_IRUGO, show_write, set_write);
 
+static struct attribute *pcf8574_attributes[] = {
+	&dev_attr_read.attr,
+	&dev_attr_write.attr,
+	NULL
+};
+
+static const struct attribute_group pcf8574_attr_group = {
+	.attrs = pcf8574_attributes,
+};
+
 /*
  * Real code
  */
@@ -166,13 +176,13 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
 	pcf8574_init_client(new_client);
 
 	/* Register sysfs hooks */
-	device_create_file(&new_client->dev, &dev_attr_read);
-	device_create_file(&new_client->dev, &dev_attr_write);
+	err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group);
+	if (err)
+		goto exit_detach;
 	return 0;
 
-/* OK, this is not exactly good programming practice, usually. But it is
-   very code-efficient in this case. */
-
+      exit_detach:
+	i2c_detach_client(new_client);
       exit_free:
 	kfree(data);
       exit:
@@ -183,6 +193,8 @@ static int pcf8574_detach_client(struct i2c_client *client)
 {
 	int err;
 
+	sysfs_remove_group(&client->dev.kobj, &pcf8574_attr_group);
+
 	if ((err = i2c_detach_client(client)))
 		return err;
 

+ 45 - 13
drivers/i2c/chips/pcf8591.c

@@ -158,6 +158,28 @@ static ssize_t set_out0_enable(struct device *dev, struct device_attribute *attr
 static DEVICE_ATTR(out0_enable, S_IWUSR | S_IRUGO, 
 		   show_out0_enable, set_out0_enable);
 
+static struct attribute *pcf8591_attributes[] = {
+	&dev_attr_out0_enable.attr,
+	&dev_attr_out0_output.attr,
+	&dev_attr_in0_input.attr,
+	&dev_attr_in1_input.attr,
+	NULL
+};
+
+static const struct attribute_group pcf8591_attr_group = {
+	.attrs = pcf8591_attributes,
+};
+
+static struct attribute *pcf8591_attributes_opt[] = {
+	&dev_attr_in2_input.attr,
+	&dev_attr_in3_input.attr,
+	NULL
+};
+
+static const struct attribute_group pcf8591_attr_group_opt = {
+	.attrs = pcf8591_attributes_opt,
+};
+
 /*
  * Real code
  */
@@ -211,24 +233,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
 	pcf8591_init_client(new_client);
 
 	/* Register sysfs hooks */
-	device_create_file(&new_client->dev, &dev_attr_out0_enable);
-	device_create_file(&new_client->dev, &dev_attr_out0_output);
-	device_create_file(&new_client->dev, &dev_attr_in0_input);
-	device_create_file(&new_client->dev, &dev_attr_in1_input);
+	err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
+	if (err)
+		goto exit_detach;
 
 	/* Register input2 if not in "two differential inputs" mode */
-	if (input_mode != 3 )
-		device_create_file(&new_client->dev, &dev_attr_in2_input);
-		
+	if (input_mode != 3) {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_in2_input)))
+			goto exit_sysfs_remove;
+	}
+
 	/* Register input3 only in "four single ended inputs" mode */
-	if (input_mode == 0)
-		device_create_file(&new_client->dev, &dev_attr_in3_input);
-	
+	if (input_mode == 0) {
+		if ((err = device_create_file(&new_client->dev,
+					      &dev_attr_in3_input)))
+			goto exit_sysfs_remove;
+	}
+
 	return 0;
-	
-	/* OK, this is not exactly good programming practice, usually. But it is
-	   very code-efficient in this case. */
 
+exit_sysfs_remove:
+	sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
+	sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
+exit_detach:
+	i2c_detach_client(new_client);
 exit_kfree:
 	kfree(data);
 exit:
@@ -239,6 +268,9 @@ static int pcf8591_detach_client(struct i2c_client *client)
 {
 	int err;
 
+	sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
+	sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
+
 	if ((err = i2c_detach_client(client)))
 		return err;
 

+ 55 - 17
drivers/i2c/i2c-core.c

@@ -183,15 +183,21 @@ int i2c_add_adapter(struct i2c_adapter *adap)
 	sprintf(adap->dev.bus_id, "i2c-%d", adap->nr);
 	adap->dev.driver = &i2c_adapter_driver;
 	adap->dev.release = &i2c_adapter_dev_release;
-	device_register(&adap->dev);
-	device_create_file(&adap->dev, &dev_attr_name);
+	res = device_register(&adap->dev);
+	if (res)
+		goto out_list;
+	res = device_create_file(&adap->dev, &dev_attr_name);
+	if (res)
+		goto out_unregister;
 
 	/* Add this adapter to the i2c_adapter class */
 	memset(&adap->class_dev, 0x00, sizeof(struct class_device));
 	adap->class_dev.dev = &adap->dev;
 	adap->class_dev.class = &i2c_adapter_class;
 	strlcpy(adap->class_dev.class_id, adap->dev.bus_id, BUS_ID_SIZE);
-	class_device_register(&adap->class_dev);
+	res = class_device_register(&adap->class_dev);
+	if (res)
+		goto out_remove_name;
 
 	dev_dbg(&adap->dev, "adapter [%s] registered\n", adap->name);
 
@@ -206,6 +212,17 @@ int i2c_add_adapter(struct i2c_adapter *adap)
 out_unlock:
 	mutex_unlock(&core_lists);
 	return res;
+
+out_remove_name:
+	device_remove_file(&adap->dev, &dev_attr_name);
+out_unregister:
+	init_completion(&adap->dev_released); /* Needed? */
+	device_unregister(&adap->dev);
+	wait_for_completion(&adap->dev_released);
+out_list:
+	list_del(&adap->list);
+	idr_remove(&i2c_adapter_idr, adap->nr);
+	goto out_unlock;
 }
 
 
@@ -394,14 +411,14 @@ int i2c_check_addr(struct i2c_adapter *adapter, int addr)
 int i2c_attach_client(struct i2c_client *client)
 {
 	struct i2c_adapter *adapter = client->adapter;
+	int res = 0;
 
 	mutex_lock(&adapter->clist_lock);
 	if (__i2c_check_addr(client->adapter, client->addr)) {
-		mutex_unlock(&adapter->clist_lock);
-		return -EBUSY;
+		res = -EBUSY;
+		goto out_unlock;
 	}
 	list_add_tail(&client->list,&adapter->clients);
-	mutex_unlock(&adapter->clist_lock);
 	
 	if (adapter->client_register)  {
 		if (adapter->client_register(client))  {
@@ -422,10 +439,26 @@ int i2c_attach_client(struct i2c_client *client)
 		"%d-%04x", i2c_adapter_id(adapter), client->addr);
 	dev_dbg(&adapter->dev, "client [%s] registered with bus id %s\n",
 		client->name, client->dev.bus_id);
-	device_register(&client->dev);
-	device_create_file(&client->dev, &dev_attr_client_name);
-	
-	return 0;
+	res = device_register(&client->dev);
+	if (res)
+		goto out_list;
+	res = device_create_file(&client->dev, &dev_attr_client_name);
+	if (res)
+		goto out_unregister;
+
+out_unlock:
+	mutex_unlock(&adapter->clist_lock);
+	return res;
+
+out_unregister:
+	init_completion(&client->released); /* Needed? */
+	device_unregister(&client->dev);
+	wait_for_completion(&client->released);
+out_list:
+	list_del(&client->list);
+	dev_err(&adapter->dev, "Failed to attach i2c client %s at 0x%02x "
+		"(%d)\n", client->name, client->addr, res);
+	goto out_unlock;
 }
 
 
@@ -674,11 +707,16 @@ static int i2c_probe_address(struct i2c_adapter *adapter, int addr, int kind,
 
 	/* Finally call the custom detection function */
 	err = found_proc(adapter, addr, kind);
-
 	/* -ENODEV can be returned if there is a chip at the given address
 	   but it isn't supported by this chip driver. We catch it here as
 	   this isn't an error. */
-	return (err == -ENODEV) ? 0 : err;
+	if (err == -ENODEV)
+		err = 0;
+
+	if (err)
+		dev_warn(&adapter->dev, "Client creation failed at 0x%x (%d)\n",
+			 addr, err);
+	return err;
 }
 
 int i2c_probe(struct i2c_adapter *adapter,
@@ -868,7 +906,7 @@ s32 i2c_smbus_read_byte(struct i2c_client *client)
 	                   I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
 		return -1;
 	else
-		return 0x0FF & data.byte;
+		return data.byte;
 }
 
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
@@ -884,7 +922,7 @@ s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
 	                   I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
 		return -1;
 	else
-		return 0x0FF & data.byte;
+		return data.byte;
 }
 
 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
@@ -903,7 +941,7 @@ s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
 	                   I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
 		return -1;
 	else
-		return 0x0FFFF & data.word;
+		return data.word;
 }
 
 s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
@@ -1006,7 +1044,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
 		else {
 			msg[0].len=3;
 			msgbuf0[1] = data->word & 0xff;
-			msgbuf0[2] = (data->word >> 8) & 0xff;
+			msgbuf0[2] = data->word >> 8;
 		}
 		break;
 	case I2C_SMBUS_PROC_CALL:
@@ -1015,7 +1053,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
 		msg[0].len = 3;
 		msg[1].len = 2;
 		msgbuf0[1] = data->word & 0xff;
-		msgbuf0[2] = (data->word >> 8) & 0xff;
+		msgbuf0[2] = data->word >> 8;
 		break;
 	case I2C_SMBUS_BLOCK_DATA:
 		if (read_write == I2C_SMBUS_READ) {

+ 50 - 59
drivers/i2c/i2c-dev.c

@@ -32,43 +32,35 @@
 #include <linux/slab.h>
 #include <linux/smp_lock.h>
 #include <linux/init.h>
+#include <linux/list.h>
 #include <linux/i2c.h>
 #include <linux/i2c-dev.h>
-#include <linux/platform_device.h>
 #include <asm/uaccess.h>
 
-static struct i2c_client i2cdev_client_template;
+static struct i2c_driver i2cdev_driver;
 
 struct i2c_dev {
-	int minor;
+	struct list_head list;
 	struct i2c_adapter *adap;
 	struct class_device *class_dev;
 };
-#define to_i2c_dev(d) container_of(d, struct i2c_dev, class_dev)
 
 #define I2C_MINORS	256
-static struct i2c_dev *i2c_dev_array[I2C_MINORS];
-static DEFINE_SPINLOCK(i2c_dev_array_lock);
+static LIST_HEAD(i2c_dev_list);
+static DEFINE_SPINLOCK(i2c_dev_list_lock);
 
 static struct i2c_dev *i2c_dev_get_by_minor(unsigned index)
 {
 	struct i2c_dev *i2c_dev;
 
-	spin_lock(&i2c_dev_array_lock);
-	i2c_dev = i2c_dev_array[index];
-	spin_unlock(&i2c_dev_array_lock);
-	return i2c_dev;
-}
-
-static struct i2c_dev *i2c_dev_get_by_adapter(struct i2c_adapter *adap)
-{
-	struct i2c_dev *i2c_dev = NULL;
-
-	spin_lock(&i2c_dev_array_lock);
-	if ((i2c_dev_array[adap->nr]) &&
-	    (i2c_dev_array[adap->nr]->adap == adap))
-		i2c_dev = i2c_dev_array[adap->nr];
-	spin_unlock(&i2c_dev_array_lock);
+	spin_lock(&i2c_dev_list_lock);
+	list_for_each_entry(i2c_dev, &i2c_dev_list, list) {
+		if (i2c_dev->adap->nr == index)
+			goto found;
+	}
+	i2c_dev = NULL;
+found:
+	spin_unlock(&i2c_dev_list_lock);
 	return i2c_dev;
 }
 
@@ -76,30 +68,28 @@ static struct i2c_dev *get_free_i2c_dev(struct i2c_adapter *adap)
 {
 	struct i2c_dev *i2c_dev;
 
+	if (adap->nr >= I2C_MINORS) {
+		printk(KERN_ERR "i2c-dev: Out of device minors (%d)\n",
+		       adap->nr);
+		return ERR_PTR(-ENODEV);
+	}
+
 	i2c_dev = kzalloc(sizeof(*i2c_dev), GFP_KERNEL);
 	if (!i2c_dev)
 		return ERR_PTR(-ENOMEM);
+	i2c_dev->adap = adap;
 
-	spin_lock(&i2c_dev_array_lock);
-	if (i2c_dev_array[adap->nr]) {
-		spin_unlock(&i2c_dev_array_lock);
-		dev_err(&adap->dev, "i2c-dev already has a device assigned to this adapter\n");
-		goto error;
-	}
-	i2c_dev->minor = adap->nr;
-	i2c_dev_array[adap->nr] = i2c_dev;
-	spin_unlock(&i2c_dev_array_lock);
+	spin_lock(&i2c_dev_list_lock);
+	list_add_tail(&i2c_dev->list, &i2c_dev_list);
+	spin_unlock(&i2c_dev_list_lock);
 	return i2c_dev;
-error:
-	kfree(i2c_dev);
-	return ERR_PTR(-ENODEV);
 }
 
 static void return_i2c_dev(struct i2c_dev *i2c_dev)
 {
-	spin_lock(&i2c_dev_array_lock);
-	i2c_dev_array[i2c_dev->minor] = NULL;
-	spin_unlock(&i2c_dev_array_lock);
+	spin_lock(&i2c_dev_list_lock);
+	list_del(&i2c_dev->list);
+	spin_unlock(&i2c_dev_list_lock);
 }
 
 static ssize_t show_adapter_name(struct class_device *class_dev, char *buf)
@@ -375,12 +365,13 @@ static int i2cdev_open(struct inode *inode, struct file *file)
 	if (!adap)
 		return -ENODEV;
 
-	client = kmalloc(sizeof(*client), GFP_KERNEL);
+	client = kzalloc(sizeof(*client), GFP_KERNEL);
 	if (!client) {
 		i2c_put_adapter(adap);
 		return -ENOMEM;
 	}
-	memcpy(client, &i2cdev_client_template, sizeof(*client));
+	snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
+	client->driver = &i2cdev_driver;
 
 	/* registered with adapter, passed as client to user */
 	client->adapter = adap;
@@ -415,41 +406,47 @@ static struct class *i2c_dev_class;
 static int i2cdev_attach_adapter(struct i2c_adapter *adap)
 {
 	struct i2c_dev *i2c_dev;
-	struct device *dev;
+	int res;
 
 	i2c_dev = get_free_i2c_dev(adap);
 	if (IS_ERR(i2c_dev))
 		return PTR_ERR(i2c_dev);
 
-	pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
-		 adap->name, i2c_dev->minor);
-
 	/* register this i2c device with the driver core */
-	i2c_dev->adap = adap;
-	dev = &adap->dev;
 	i2c_dev->class_dev = class_device_create(i2c_dev_class, NULL,
-						 MKDEV(I2C_MAJOR, i2c_dev->minor),
-						 dev, "i2c-%d", i2c_dev->minor);
-	if (!i2c_dev->class_dev)
+						 MKDEV(I2C_MAJOR, adap->nr),
+						 &adap->dev, "i2c-%d",
+						 adap->nr);
+	if (!i2c_dev->class_dev) {
+		res = -ENODEV;
 		goto error;
-	class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+	}
+	res = class_device_create_file(i2c_dev->class_dev, &class_device_attr_name);
+	if (res)
+		goto error_destroy;
+
+	pr_debug("i2c-dev: adapter [%s] registered as minor %d\n",
+		 adap->name, adap->nr);
 	return 0;
+error_destroy:
+	class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
 error:
 	return_i2c_dev(i2c_dev);
 	kfree(i2c_dev);
-	return -ENODEV;
+	return res;
 }
 
 static int i2cdev_detach_adapter(struct i2c_adapter *adap)
 {
 	struct i2c_dev *i2c_dev;
 
-	i2c_dev = i2c_dev_get_by_adapter(adap);
-	if (!i2c_dev)
-		return -ENODEV;
+	i2c_dev = i2c_dev_get_by_minor(adap->nr);
+	if (!i2c_dev) /* attach_adapter must have failed */
+		return 0;
 
+	class_device_remove_file(i2c_dev->class_dev, &class_device_attr_name);
 	return_i2c_dev(i2c_dev);
-	class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, i2c_dev->minor));
+	class_device_destroy(i2c_dev_class, MKDEV(I2C_MAJOR, adap->nr));
 	kfree(i2c_dev);
 
 	pr_debug("i2c-dev: adapter [%s] unregistered\n", adap->name);
@@ -471,12 +468,6 @@ static struct i2c_driver i2cdev_driver = {
 	.detach_client	= i2cdev_detach_client,
 };
 
-static struct i2c_client i2cdev_client_template = {
-	.name		= "I2C /dev entry",
-	.addr		= -1,
-	.driver		= &i2cdev_driver,
-};
-
 static int __init i2c_dev_init(void)
 {
 	int res;

+ 0 - 1
drivers/ieee1394/pcilynx.c

@@ -137,7 +137,6 @@ static struct i2c_algo_bit_data bit_data = {
 	.getsda			= bit_getsda,
 	.getscl			= bit_getscl,
 	.udelay			= 5,
-	.mdelay			= 5,
 	.timeout		= 100,
 };
 

+ 0 - 1
drivers/media/video/bt8xx/bttv-i2c.c

@@ -100,7 +100,6 @@ static struct i2c_algo_bit_data bttv_i2c_algo_bit_template = {
 	.getsda  = bttv_bit_getsda,
 	.getscl  = bttv_bit_getscl,
 	.udelay  = 16,
-	.mdelay  = 10,
 	.timeout = 200,
 };
 

+ 0 - 1
drivers/media/video/cx88/cx88-i2c.c

@@ -155,7 +155,6 @@ static struct i2c_algo_bit_data cx8800_i2c_algo_template = {
 	.getsda  = cx8800_bit_getsda,
 	.getscl  = cx8800_bit_getscl,
 	.udelay  = 16,
-	.mdelay  = 10,
 	.timeout = 200,
 };
 

+ 0 - 1
drivers/media/video/cx88/cx88-vp3054-i2c.c

@@ -100,7 +100,6 @@ static struct i2c_algo_bit_data vp3054_i2c_algo_template = {
 	.getsda  = vp3054_bit_getsda,
 	.getscl  = vp3054_bit_getscl,
 	.udelay  = 16,
-	.mdelay  = 10,
 	.timeout = 200,
 };
 

+ 0 - 1
drivers/media/video/zoran_card.c

@@ -820,7 +820,6 @@ static struct i2c_algo_bit_data zoran_i2c_bit_data_template = {
 	.getsda = zoran_i2c_getsda,
 	.getscl = zoran_i2c_getscl,
 	.udelay = 10,
-	.mdelay = 0,
 	.timeout = 100,
 };
 

+ 0 - 1
drivers/video/i810/i810-i2c.c

@@ -98,7 +98,6 @@ static int i810_setup_i2c_bus(struct i810fb_i2c_chan *chan, const char *name)
 	chan->algo.getsda               = i810i2c_getsda;
 	chan->algo.getscl               = i810i2c_getscl;
 	chan->algo.udelay               = 10;
-	chan->algo.mdelay               = 10;
         chan->algo.timeout              = (HZ/2);
         chan->algo.data                 = chan;
 

+ 6 - 6
drivers/video/matrox/i2c-matroxfb.c

@@ -95,12 +95,12 @@ static struct i2c_adapter matrox_i2c_adapter_template =
 
 static struct i2c_algo_bit_data matrox_i2c_algo_template =
 {
-	NULL,
-	matroxfb_gpio_setsda,
-	matroxfb_gpio_setscl,
-	matroxfb_gpio_getsda,
-	matroxfb_gpio_getscl,
-	10, 10, 100,
+	.setsda		= matroxfb_gpio_setsda,
+	.setscl		= matroxfb_gpio_setscl,
+	.getsda		= matroxfb_gpio_getsda,
+	.getscl		= matroxfb_gpio_getscl,
+	.udelay		= 10,
+	.timeout	= 100,
 };
 
 static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 

+ 0 - 1
drivers/video/savage/savagefb-i2c.c

@@ -148,7 +148,6 @@ static int savage_setup_i2c_bus(struct savagefb_i2c_chan *chan,
 		chan->adapter.algo_data		= &chan->algo;
 		chan->adapter.dev.parent	= &chan->par->pcidev->dev;
 		chan->algo.udelay		= 40;
-		chan->algo.mdelay               = 5;
 		chan->algo.timeout		= 20;
 		chan->algo.data 		= chan;
 

+ 0 - 1
include/linux/i2c-algo-bit.h

@@ -40,7 +40,6 @@ struct i2c_algo_bit_data {
 	/* local settings */
 	int udelay;		/* half-clock-cycle time in microsecs */
 				/* i.e. clock is (500 / udelay) KHz */
-	int mdelay;		/* in millisecs, unused */
 	int timeout;		/* in jiffies */
 };
 

+ 0 - 1
include/linux/i2c-algo-pcf.h

@@ -35,7 +35,6 @@ struct i2c_algo_pcf_data {
 
 	/* local settings */
 	int udelay;
-	int mdelay;
 	int timeout;
 };
 

+ 0 - 33
include/linux/i2c-algo-sibyte.h

@@ -1,33 +0,0 @@
-/*
- * Copyright (C) 2001,2002,2003 Broadcom Corporation
- *
- * 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., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
- */
-
-#ifndef I2C_ALGO_SIBYTE_H
-#define I2C_ALGO_SIBYTE_H 1
-
-#include <linux/i2c.h>
-
-struct i2c_algo_sibyte_data {
-	void *data;		/* private data */
-        int   bus;		/* which bus */
-        void *reg_base;		/* CSR base */
-};
-
-int i2c_sibyte_add_bus(struct i2c_adapter *, int speed);
-int i2c_sibyte_del_bus(struct i2c_adapter *);
-
-#endif /* I2C_ALGO_SIBYTE_H */

+ 1 - 13
include/linux/i2c.h

@@ -64,14 +64,6 @@ extern int i2c_master_recv(struct i2c_client *,char* ,int);
  */
 extern int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num);
 
-/*
- * Some adapter types (i.e. PCF 8584 based ones) may support slave behaviuor. 
- * This is not tested/implemented yet and will change in the future.
- */
-extern int i2c_slave_send(struct i2c_client *,char*,int);
-extern int i2c_slave_recv(struct i2c_client *,char*,int);
-
-
 
 /* This is the very generalized SMBus access routine. You probably do not
    want to use this, though; one of the functions below may be much easier,
@@ -201,10 +193,6 @@ struct i2c_algorithm {
 	                   unsigned short flags, char read_write,
 	                   u8 command, int size, union i2c_smbus_data * data);
 
-	/* --- these optional/future use for some adapter types.*/
-	int (*slave_send)(struct i2c_adapter *,char*,int);
-	int (*slave_recv)(struct i2c_adapter *,char*,int);
-
 	/* --- ioctl like call to set div. parameters. */
 	int (*algo_control)(struct i2c_adapter *, unsigned int, unsigned long);
 
@@ -220,7 +208,7 @@ struct i2c_adapter {
 	struct module *owner;
 	unsigned int id;
 	unsigned int class;
-	struct i2c_algorithm *algo;/* the algorithm to access the bus	*/
+	const struct i2c_algorithm *algo; /* the algorithm to access the bus */
 	void *algo_data;
 
 	/* --- administration stuff. */