Merge master.kernel.org:/pub/scm/linux/kernel/git/gregkh/i2c-2.6
authorLinus Torvalds <torvalds@g5.osdl.org>
Wed, 27 Sep 2006 15:09:48 +0000 (08:09 -0700)
committerLinus Torvalds <torvalds@g5.osdl.org>
Wed, 27 Sep 2006 15:09:48 +0000 (08:09 -0700)
* 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
  ...

83 files changed:
Documentation/feature-removal-schedule.txt
Documentation/i2c/busses/i2c-viapro
Documentation/i2c/i2c-stub
drivers/acorn/char/i2c.c
drivers/acpi/i2c_ec.c
drivers/hwmon/it87.c
drivers/hwmon/lm78.c
drivers/hwmon/pc87360.c
drivers/hwmon/sis5595.c
drivers/hwmon/smsc47b397.c
drivers/hwmon/smsc47m1.c
drivers/hwmon/via686a.c
drivers/hwmon/vt8231.c
drivers/hwmon/w83627ehf.c
drivers/hwmon/w83627hf.c
drivers/hwmon/w83781d.c
drivers/i2c/Kconfig
drivers/i2c/algos/Kconfig
drivers/i2c/algos/Makefile
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
drivers/i2c/algos/i2c-algo-sgi.c
drivers/i2c/algos/i2c-algo-sibyte.c [deleted file]
drivers/i2c/busses/Kconfig
drivers/i2c/busses/Makefile
drivers/i2c/busses/i2c-ali1535.c
drivers/i2c/busses/i2c-ali1563.c
drivers/i2c/busses/i2c-ali15x3.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i810.c
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isa.c
drivers/i2c/busses/i2c-ixp2000.c
drivers/i2c/busses/i2c-ixp4xx.c
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-omap.c [new file with mode: 0644]
drivers/i2c/busses/i2c-parport-light.c
drivers/i2c/busses/i2c-parport.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-powermac.c
drivers/i2c/busses/i2c-prosavage.c
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-savage4.c
drivers/i2c/busses/i2c-sibyte.c
drivers/i2c/busses/i2c-sis5595.c
drivers/i2c/busses/i2c-sis630.c
drivers/i2c/busses/i2c-sis96x.c
drivers/i2c/busses/i2c-stub.c
drivers/i2c/busses/i2c-via.c
drivers/i2c/busses/i2c-viapro.c
drivers/i2c/busses/i2c-voodoo3.c
drivers/i2c/busses/scx200_acb.c
drivers/i2c/busses/scx200_i2c.c
drivers/i2c/chips/eeprom.c
drivers/i2c/chips/max6875.c
drivers/i2c/chips/pca9539.c
drivers/i2c/chips/pcf8574.c
drivers/i2c/chips/pcf8591.c
drivers/i2c/i2c-core.c
drivers/i2c/i2c-dev.c
drivers/ieee1394/pcilynx.c
drivers/media/video/bt8xx/bttv-i2c.c
drivers/media/video/cx88/cx88-i2c.c
drivers/media/video/cx88/cx88-vp3054-i2c.c
drivers/media/video/zoran_card.c
drivers/video/i810/i810-i2c.c
drivers/video/matrox/i2c-matroxfb.c
drivers/video/savage/savagefb-i2c.c
include/linux/i2c-algo-bit.h
include/linux/i2c-algo-pcf.h
include/linux/i2c-algo-sibyte.h [deleted file]
include/linux/i2c.h

index bf56b20..93b10bd 100644 (file)
@@ -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>
+
+---------------------------
index 1677566..2568034 100644 (file)
@@ -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.
index d6dcb13..9cc081e 100644 (file)
@@ -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.
 
index c26c08b..bdb9c8b 100644 (file)
@@ -308,7 +308,6 @@ static struct i2c_algo_bit_data ioc_data = {
        .getsda         = ioc_getsda,
        .getscl         = ioc_getscl,
        .udelay         = 80,
-       .mdelay         = 80,
        .timeout        = 100
 };
 
index 6809c28..6342e61 100644 (file)
@@ -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,
 };
index 06df92b..b0ee574 100644 (file)
@@ -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,
index a6ce7ab..fa1715b 100644 (file)
@@ -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,
index ae05e48..236f9f2 100644 (file)
@@ -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,
index 063f71c..3783af4 100644 (file)
@@ -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,
index b608618..a858693 100644 (file)
@@ -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,
index 825e8f7..6c81b84 100644 (file)
@@ -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,
index 166298f..95ae056 100644 (file)
@@ -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,
index 686f3de..236ccf0 100644 (file)
@@ -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,
index 40301bc..b21d6b9 100644 (file)
@@ -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,
index 79368d5..3029502 100644 (file)
@@ -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,
index 7be469e..95221b1 100644 (file)
@@ -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,
index 24383af..11935f6 100644 (file)
@@ -1,5 +1,5 @@
 #
-# Character device configuration
+# I2C subsystem configuration
 #
 
 menu "I2C support"
index 3040801..c034820 100644 (file)
@@ -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)
index 867fe1f..208be04 100644 (file)
@@ -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)
index ab230c0..21c36bf 100644 (file)
@@ -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,
 };
index b88a6fc..9081c9f 100644 (file)
@@ -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,
 };
index 5b24930..3b20033 100644 (file)
@@ -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,
 };
index 932c4fa..490d999 100644 (file)
@@ -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,
 };
diff --git a/drivers/i2c/algos/i2c-algo-sibyte.c b/drivers/i2c/algos/i2c-algo-sibyte.c
deleted file mode 100644 (file)
index 32d41c6..0000000
+++ /dev/null
@@ -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
index 884320e..9e56c39 100644 (file)
@@ -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.
index ac56df5..493c872 100644 (file)
@@ -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
index d3ef46a..e75d339 100644 (file)
@@ -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,
 };
index e6f6320..33fbb47 100644 (file)
@@ -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,
 };
index 7a5c094..3f11b6e 100644 (file)
@@ -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,
 };
index 1750ded..2d21afd 100644 (file)
@@ -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,
 };
index e5ef560..0fbc718 100644 (file)
@@ -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,
 };
index d06edce..d7e7c35 100644 (file)
@@ -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,
 };
index 59f8308..caa8e5c 100644 (file)
@@ -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,
 };
 
index e0cb3b0..457d48a 100644 (file)
@@ -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
 };
 
index 7be1d0a..bbb2fbe 100644 (file)
@@ -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,
 };
index 748be30..b66fb6b 100644 (file)
@@ -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,
 };
 
index 0599bbd..5bccb5d 100644 (file)
@@ -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
 };
index 48c5693..8e41315 100644 (file)
@@ -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,
index c3e1d3e..4380653 100644 (file)
@@ -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)
index cd6f45d..dd3f4cd 100644 (file)
@@ -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,
index 2ed0711..ab57325 100644 (file)
@@ -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;
index 377ab40..155a986 100644 (file)
@@ -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,
 };
index ac5cde1..eacbaf7 100644 (file)
@@ -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,
 };
index 604b49e..e0292e4 100644 (file)
@@ -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,
 };
index 5928240..952a28d 100644 (file)
@@ -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,
 };
diff --git a/drivers/i2c/busses/i2c-omap.c b/drivers/i2c/busses/i2c-omap.c
new file mode 100644 (file)
index 0000000..81d87d2
--- /dev/null
@@ -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");
index e09ebbb..5eb2bd2 100644 (file)
@@ -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,
 }; 
 
index 934bd55..48a8294 100644 (file)
@@ -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,
 }; 
 
index 8f2f65b..30c7a1b 100644 (file)
@@ -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,
 };
index d658d91..a508cb9 100644 (file)
@@ -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,
index 9479525..7745e21 100644 (file)
@@ -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;
index ee114b4..cd4ad98 100644 (file)
@@ -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,
 };
index 5d2950e..9ebe429 100644 (file)
@@ -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,
 };
index 0c85182..209f47e 100644 (file)
@@ -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
 };
 
index fa503ed..8f2b1f0 100644 (file)
@@ -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
  * 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");
index b57ab74..38bbfd8 100644 (file)
@@ -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,
 };
index acb75e2..dec0baf 100644 (file)
@@ -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,
 };
index 1a73c05..7fd07fb 100644 (file)
@@ -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,
 };
index 73f481e..a54adc5 100644 (file)
 #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);
 }
 
index 484bbac..910e200 100644 (file)
@@ -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
 };
 
index 47e52bf..efc6bbf 100644 (file)
@@ -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, }
 };
 
index b675773..6c8d251 100644 (file)
@@ -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
 };
 
index eae9e81..32aab0d 100644 (file)
@@ -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,
 };
index cb3ef5a..8b65a5c 100644 (file)
@@ -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 = {
index 13c1082..cec3a0c 100644 (file)
@@ -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;
index 88d2dde..76645c1 100644 (file)
@@ -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;
 }
 
index cb22280..f43c4e7 100644 (file)
@@ -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;
 
index c3e6449..32b2542 100644 (file)
@@ -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;
 
index 925a6b3..4dc3637 100644 (file)
@@ -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;
 
index 9cb277d..01233f0 100644 (file)
@@ -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) {
index 58ccddd..3f86903 100644 (file)
 #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;
index e6f4123..b4f146f 100644 (file)
@@ -137,7 +137,6 @@ static struct i2c_algo_bit_data bit_data = {
        .getsda                 = bit_getsda,
        .getscl                 = bit_getscl,
        .udelay                 = 5,
-       .mdelay                 = 5,
        .timeout                = 100,
 };
 
index 4b562b3..0dfbcc8 100644 (file)
@@ -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,
 };
 
index 7066380..7bea347 100644 (file)
@@ -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,
 };
 
index 751a754..2b4f197 100644 (file)
@@ -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,
 };
 
index f2249ed..29f59c3 100644 (file)
@@ -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,
 };
 
index c1f7b49..7d06b38 100644 (file)
@@ -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;
 
index 57abbae..795c1a9 100644 (file)
@@ -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, 
index e83befd..d7d810d 100644 (file)
@@ -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;
 
index c0e7fab..c8f8df2 100644 (file)
@@ -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 */
 };
 
index 18b0adf..9908f3f 100644 (file)
@@ -35,7 +35,6 @@ struct i2c_algo_pcf_data {
 
        /* local settings */
        int udelay;
-       int mdelay;
        int timeout;
 };
 
diff --git a/include/linux/i2c-algo-sibyte.h b/include/linux/i2c-algo-sibyte.h
deleted file mode 100644 (file)
index 03914de..0000000
+++ /dev/null
@@ -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 */
index eb0628a..9b5d047 100644 (file)
@@ -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. */