]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/commitdiff
Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 15 Jul 2008 18:16:05 +0000 (11:16 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 15 Jul 2008 18:16:05 +0000 (11:16 -0700)
* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: (56 commits)
  i2c: Add detection capability to new-style drivers
  i2c: Call client_unregister for new-style devices too
  i2c: Clean up old chip drivers
  i2c-ibm_iic: Register child nodes
  i2c: New-style EEPROM driver using device IDs
  i2c: Export the i2c_bus_type symbol
  i2c-au1550: Fix PM support
  i2c-dev: Delete empty detach_client callback
  i2c: Drop stray references to lm_sensors
  i2c: Check for ACPI resource conflicts
  i2c-ocores: basic PM support
  i2c-sibyte: SWARM I2C board initialization
  i2c-i801: Fix handling of error conditions
  i2c-i801: Rename local variable temp to status
  i2c-i801: Properly report bus arbitration loss
  i2c-i801: Remove verbose debugging messages
  i2c-algo-pcf: Drop unused struct members
  i2c-algo-pcf: Multi-master lost-arbitration improvement
  i2c: Deprecate the legacy gpio drivers
  i2c-pxa: Initialize early
  ...

72 files changed:
Documentation/feature-removal-schedule.txt
Documentation/i2c/busses/i2c-i810 [deleted file]
Documentation/i2c/busses/i2c-prosavage [deleted file]
Documentation/i2c/busses/i2c-savage4 [deleted file]
Documentation/i2c/fault-codes [new file with mode: 0644]
Documentation/i2c/smbus-protocol
Documentation/i2c/writing-clients
MAINTAINERS
arch/mips/sibyte/swarm/Makefile
arch/mips/sibyte/swarm/swarm-i2c.c [new file with mode: 0644]
drivers/i2c/algos/i2c-algo-bit.c
drivers/i2c/algos/i2c-algo-pca.c
drivers/i2c/algos/i2c-algo-pcf.c
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-s4882.c
drivers/i2c/busses/i2c-amd756.c
drivers/i2c/busses/i2c-amd8111.c
drivers/i2c/busses/i2c-au1550.c
drivers/i2c/busses/i2c-cpm.c [new file with mode: 0644]
drivers/i2c/busses/i2c-davinci.c
drivers/i2c/busses/i2c-elektor.c
drivers/i2c/busses/i2c-gpio.c
drivers/i2c/busses/i2c-hydra.c
drivers/i2c/busses/i2c-i801.c
drivers/i2c/busses/i2c-i810.c [deleted file]
drivers/i2c/busses/i2c-ibm_iic.c
drivers/i2c/busses/i2c-iop3xx.c
drivers/i2c/busses/i2c-isch.c [new file with mode: 0644]
drivers/i2c/busses/i2c-mpc.c
drivers/i2c/busses/i2c-mv64xxx.c
drivers/i2c/busses/i2c-nforce2-s4985.c [new file with mode: 0644]
drivers/i2c/busses/i2c-nforce2.c
drivers/i2c/busses/i2c-ocores.c
drivers/i2c/busses/i2c-pasemi.c
drivers/i2c/busses/i2c-pca-platform.c
drivers/i2c/busses/i2c-piix4.c
drivers/i2c/busses/i2c-pmcmsp.c
drivers/i2c/busses/i2c-prosavage.c [deleted file]
drivers/i2c/busses/i2c-pxa.c
drivers/i2c/busses/i2c-s3c2410.c
drivers/i2c/busses/i2c-savage4.c [deleted file]
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-taos-evm.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/chips/Kconfig
drivers/i2c/chips/Makefile
drivers/i2c/chips/at24.c [new file with mode: 0644]
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/video/fb_ddc.c
drivers/video/intelfb/intelfb_i2c.c
drivers/video/matrox/i2c-matroxfb.c
include/linux/i2c-algo-pcf.h
include/linux/i2c-id.h
include/linux/i2c.h
include/linux/i2c/at24.h [new file with mode: 0644]

index 46ece3fba6f94c2924c94d6f96b4402984705102..65a1482457a89ec9d6c5beec89464bc049f3f5e2 100644 (file)
@@ -222,13 +222,6 @@ Who:       Thomas Gleixner <tglx@linutronix.de>
 
 ---------------------------
 
-What:  i2c-i810, i2c-prosavage and i2c-savage4
-When:  May 2008
-Why:   These drivers are superseded by i810fb, intelfb and savagefb.
-Who:   Jean Delvare <khali@linux-fr.org>
-
----------------------------
-
 What (Why):
        - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files
          (superseded by xt_TOS/xt_tos target & match)
diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810
deleted file mode 100644 (file)
index 778210e..0000000
+++ /dev/null
@@ -1,47 +0,0 @@
-Kernel driver i2c-i810
-
-Supported adapters:
-  * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH)
-  * Intel 82845G (GMCH)
-
-Authors: 
-       Frodo Looijaard <frodol@dds.nl>, 
-       Philip Edelbrock <phil@netroedge.com>,
-        Kyösti Mälkki <kmalkki@cc.hut.fi>,
-       Ralph Metzler <rjkm@thp.uni-koeln.de>,
-       Mark D. Studebaker <mdsxyz123@yahoo.com>
-
-Main contact: Mark Studebaker <mdsxyz123@yahoo.com>
-
-Description 
------------ 
-
-WARNING: If you have an '810' or '815' motherboard, your standard I2C
-temperature sensors are most likely on the 801's I2C bus. You want the
-i2c-i801 driver for those, not this driver.
-
-Now for the i2c-i810...
-
-The GMCH chip contains two I2C interfaces.
-
-The first interface is used for DDC (Data Display Channel) which is a
-serial channel through the VGA monitor connector to a DDC-compliant
-monitor. This interface is defined by the Video Electronics Standards
-Association (VESA). The standards are available for purchase at
-http://www.vesa.org .
-
-The second interface is a general-purpose I2C bus. It may be connected to a
-TV-out chip such as the BT869 or possibly to a digital flat-panel display.
-
-Features
--------- 
-
-Both busses use the i2c-algo-bit driver for 'bit banging'
-and support for specific transactions is provided by i2c-algo-bit.
-
-Issues
-------
-
-If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1),
-the test may fail; if so, the i2c-i810 driver won't be inserted. However,
-we think this has been fixed.
diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage
deleted file mode 100644 (file)
index 7036879..0000000
+++ /dev/null
@@ -1,23 +0,0 @@
-Kernel driver i2c-prosavage
-
-Supported adapters:
-       
-       S3/VIA KM266/VT8375 aka ProSavage8 
-       S3/VIA KM133/VT8365 aka Savage4 
-
-Author: Henk Vergonet <henk@god.dyndns.org>
-
-Description
------------
-
-The Savage4 chips contain two I2C interfaces (aka a I2C 'master' or
-'host'). 
-
-The first interface is used for DDC (Data Display Channel) which is a
-serial channel through the VGA monitor connector to a DDC-compliant
-monitor. This interface is defined by the Video Electronics Standards
-Association (VESA). The standards are available for purchase at
-http://www.vesa.org . The second interface is a general-purpose I2C bus.
-
-Usefull for gaining access to the TV Encoder chips.
-
diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4
deleted file mode 100644 (file)
index 6ecceab..0000000
+++ /dev/null
@@ -1,26 +0,0 @@
-Kernel driver i2c-savage4
-
-Supported adapters:
-  * Savage4
-  * Savage2000
-
-Authors: 
-       Alexander Wold <awold@bigfoot.com>,
-       Mark D. Studebaker <mdsxyz123@yahoo.com> 
-
-Description
------------
-
-The Savage4 chips contain two I2C interfaces (aka a I2C 'master'
-or 'host'). 
-
-The first interface is used for DDC (Data Display Channel) which is a
-serial channel through the VGA monitor connector to a DDC-compliant
-monitor. This interface is defined by the Video Electronics Standards
-Association (VESA). The standards are available for purchase at
-http://www.vesa.org . The DDC bus is not yet supported because its register
-is not directly memory-mapped.
-
-The second interface is a general-purpose I2C bus. This is the only
-interface supported by the driver at the moment.
-
diff --git a/Documentation/i2c/fault-codes b/Documentation/i2c/fault-codes
new file mode 100644 (file)
index 0000000..045765c
--- /dev/null
@@ -0,0 +1,127 @@
+This is a summary of the most important conventions for use of fault
+codes in the I2C/SMBus stack.
+
+
+A "Fault" is not always an "Error"
+----------------------------------
+Not all fault reports imply errors; "page faults" should be a familiar
+example.  Software often retries idempotent operations after transient
+faults.  There may be fancier recovery schemes that are appropriate in
+some cases, such as re-initializing (and maybe resetting).  After such
+recovery, triggered by a fault report, there is no error.
+
+In a similar way, sometimes a "fault" code just reports one defined
+result for an operation ... it doesn't indicate that anything is wrong
+at all, just that the outcome wasn't on the "golden path".
+
+In short, your I2C driver code may need to know these codes in order
+to respond correctly.  Other code may need to rely on YOUR code reporting
+the right fault code, so that it can (in turn) behave correctly.
+
+
+I2C and SMBus fault codes
+-------------------------
+These are returned as negative numbers from most calls, with zero or
+some positive number indicating a non-fault return.  The specific
+numbers associated with these symbols differ between architectures,
+though most Linux systems use <asm-generic/errno*.h> numbering.
+
+Note that the descriptions here are not exhaustive.  There are other
+codes that may be returned, and other cases where these codes should
+be returned.  However, drivers should not return other codes for these
+cases (unless the hardware doesn't provide unique fault reports).
+
+Also, codes returned by adapter probe methods follow rules which are
+specific to their host bus (such as PCI, or the platform bus).
+
+
+EAGAIN
+       Returned by I2C adapters when they lose arbitration in master
+       transmit mode:  some other master was transmitting different
+       data at the same time.
+
+       Also returned when trying to invoke an I2C operation in an
+       atomic context, when some task is already using that I2C bus
+       to execute some other operation.
+
+EBADMSG
+       Returned by SMBus logic when an invalid Packet Error Code byte
+       is received.  This code is a CRC covering all bytes in the
+       transaction, and is sent before the terminating STOP.  This
+       fault is only reported on read transactions; the SMBus slave
+       may have a way to report PEC mismatches on writes from the
+       host.  Note that even if PECs are in use, you should not rely
+       on these as the only way to detect incorrect data transfers.
+
+EBUSY
+       Returned by SMBus adapters when the bus was busy for longer
+       than allowed.  This usually indicates some device (maybe the
+       SMBus adapter) needs some fault recovery (such as resetting),
+       or that the reset was attempted but failed.
+
+EINVAL
+       This rather vague error means an invalid parameter has been
+       detected before any I/O operation was started.  Use a more
+       specific fault code when you can.
+
+       One example would be a driver trying an SMBus Block Write
+       with block size outside the range of 1-32 bytes.
+
+EIO
+       This rather vague error means something went wrong when
+       performing an I/O operation.  Use a more specific fault
+       code when you can.
+
+ENODEV
+       Returned by driver probe() methods.  This is a bit more
+       specific than ENXIO, implying the problem isn't with the
+       address, but with the device found there.  Driver probes
+       may verify the device returns *correct* responses, and
+       return this as appropriate.  (The driver core will warn
+       about probe faults other than ENXIO and ENODEV.)
+
+ENOMEM
+       Returned by any component that can't allocate memory when
+       it needs to do so.
+
+ENXIO
+       Returned by I2C adapters to indicate that the address phase
+       of a transfer didn't get an ACK.  While it might just mean
+       an I2C device was temporarily not responding, usually it
+       means there's nothing listening at that address.
+
+       Returned by driver probe() methods to indicate that they
+       found no device to bind to.  (ENODEV may also be used.)
+
+EOPNOTSUPP
+       Returned by an adapter when asked to perform an operation
+       that it doesn't, or can't, support.
+
+       For example, this would be returned when an adapter that
+       doesn't support SMBus block transfers is asked to execute
+       one.  In that case, the driver making that request should
+       have verified that functionality was supported before it
+       made that block transfer request.
+
+       Similarly, if an I2C adapter can't execute all legal I2C
+       messages, it should return this when asked to perform a
+       transaction it can't.  (These limitations can't be seen in
+       the adapter's functionality mask, since the assumption is
+       that if an adapter supports I2C it supports all of I2C.)
+
+EPROTO
+       Returned when slave does not conform to the relevant I2C
+       or SMBus (or chip-specific) protocol specifications.  One
+       case is when the length of an SMBus block data response
+       (from the SMBus slave) is outside the range 1-32 bytes.
+
+ETIMEDOUT
+       This is returned by drivers when an operation took too much
+       time, and was aborted before it completed.
+
+       SMBus adapters may return it when an operation took more
+       time than allowed by the SMBus specification; for example,
+       when a slave stretches clocks too far.  I2C has no such
+       timeouts, but it's normal for I2C adapters to impose some
+       arbitrary limits (much longer than SMBus!) too.
+
index 03f08fb491ccca6edcbcc6ce6fd1e0dda6eae2ad..24bfb65da17dbe53db1d6f8c98562ff9c85ce5ea 100644 (file)
@@ -42,8 +42,8 @@ Count (8 bits): A data byte containing the length of a block operation.
 [..]: Data sent by I2C device, as opposed to data sent by the host adapter.
 
 
-SMBus Quick Command:  i2c_smbus_write_quick()
-=============================================
+SMBus Quick Command
+===================
 
 This sends a single bit to the device, at the place of the Rd/Wr bit.
 
index d4cd4126d1adeca025e76a2511b0881cd6d0c00c..6b61b3a2e90bee2b7cbed065160bd029db89ba08 100644 (file)
@@ -44,6 +44,10 @@ static struct i2c_driver foo_driver = {
        .id_table       = foo_ids,
        .probe          = foo_probe,
        .remove         = foo_remove,
+       /* if device autodetection is needed: */
+       .class          = I2C_CLASS_SOMETHING,
+       .detect         = foo_detect,
+       .address_data   = &addr_data,
 
        /* else, driver uses "legacy" binding model: */
        .attach_adapter = foo_attach_adapter,
@@ -217,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client
 reference for later use.
 
 
+Device Detection (Standard driver model)
+----------------------------------------
+
+Sometimes you do not know in advance which I2C devices are connected to
+a given I2C bus.  This is for example the case of hardware monitoring
+devices on a PC's SMBus.  In that case, you may want to let your driver
+detect supported devices automatically.  This is how the legacy model
+was working, and is now available as an extension to the standard
+driver model (so that we can finally get rid of the legacy model.)
+
+You simply have to define a detect callback which will attempt to
+identify supported devices (returning 0 for supported ones and -ENODEV
+for unsupported ones), a list of addresses to probe, and a device type
+(or class) so that only I2C buses which may have that type of device
+connected (and not otherwise enumerated) will be probed.  The i2c
+core will then call you back as needed and will instantiate a device
+for you for every successful detection.
+
+Note that this mechanism is purely optional and not suitable for all
+devices.  You need some reliable way to identify the supported devices
+(typically using device-specific, dedicated identification registers),
+otherwise misdetections are likely to occur and things can get wrong
+quickly.
+
+
 Device Deletion (Standard driver model)
 ---------------------------------------
 
@@ -569,7 +598,6 @@ SMBus communication
   in terms of it. Never use this function directly!
 
 
-  extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
   extern s32 i2c_smbus_read_byte(struct i2c_client * client);
   extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
   extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@@ -578,30 +606,31 @@ SMBus communication
   extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command);
   extern s32 i2c_smbus_write_word_data(struct i2c_client * client,
                                        u8 command, u16 value);
+  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
+                                       u8 command, u8 *values);
   extern s32 i2c_smbus_write_block_data(struct i2c_client * client,
                                         u8 command, u8 length,
                                         u8 *values);
   extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client,
                                            u8 command, u8 length, u8 *values);
-
-These ones were removed in Linux 2.6.10 because they had no users, but could
-be added back later if needed:
-
-  extern s32 i2c_smbus_read_block_data(struct i2c_client * client,
-                                       u8 command, u8 *values);
   extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
                                             u8 command, u8 length,
                                             u8 *values);
+
+These ones were removed from i2c-core because they had no users, but could
+be added back later if needed:
+
+  extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
   extern s32 i2c_smbus_process_call(struct i2c_client * client,
                                     u8 command, u16 value);
   extern s32 i2c_smbus_block_process_call(struct i2c_client *client,
                                           u8 command, u8 length,
                                           u8 *values)
 
-All these transactions return -1 on failure. The 'write' transactions 
-return 0 on success; the 'read' transactions return the read value, except 
-for read_block, which returns the number of values read. The block buffers 
-need not be longer than 32 bytes.
+All these transactions return a negative errno value on failure. The 'write'
+transactions return 0 on success; the 'read' transactions return the read
+value, except for block transactions, which return the number of values
+read. The block buffers need not be longer than 32 bytes.
 
 You can read the file `smbus-protocol' for more information about the
 actual SMBus protocol.
index 1528e58b540829a110eba85ad8bd0e5bea4a4c41..6198fa3deb9979b9c154677ce47a10ea72d91164 100644 (file)
@@ -1686,6 +1686,13 @@ L:       linuxppc-embedded@ozlabs.org
 L:     linux-kernel@vger.kernel.org
 S:     Maintained
 
+FREESCALE I2C CPM DRIVER
+P:     Jochen Friedrich
+M:     jochen@scram.de
+L:     linuxppc-dev@ozlabs.org
+L:     i2c@lm-sensors.org
+S:     Maintained
+
 FREESCALE SOC FS_ENET DRIVER
 P:     Pantelis Antoniou
 M:     pantelis.antoniou@gmail.com
index 1775755a2619e8359c2402db68c8c7bc5bdaeb92..255d692bfa188c6df2d59d9a167644396d4d1b15 100644 (file)
@@ -1,3 +1,4 @@
 obj-y                          := setup.o rtc_xicor1241.o rtc_m41t81.o
 
+obj-$(CONFIG_I2C_BOARDINFO)    += swarm-i2c.o
 obj-$(CONFIG_KGDB)             += dbg_io.o
diff --git a/arch/mips/sibyte/swarm/swarm-i2c.c b/arch/mips/sibyte/swarm/swarm-i2c.c
new file mode 100644 (file)
index 0000000..4282ac9
--- /dev/null
@@ -0,0 +1,37 @@
+/*
+ *     arch/mips/sibyte/swarm/swarm-i2c.c
+ *
+ *     Broadcom BCM91250A (SWARM), etc. I2C platform setup.
+ *
+ *     Copyright (c) 2008  Maciej W. Rozycki
+ *
+ *     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.
+ */
+
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/kernel.h>
+
+
+static struct i2c_board_info swarm_i2c_info1[] __initdata = {
+       {
+               I2C_BOARD_INFO("m41t81", 0x68),
+       },
+};
+
+static int __init swarm_i2c_init(void)
+{
+       int err;
+
+       err = i2c_register_board_info(1, swarm_i2c_info1,
+                                     ARRAY_SIZE(swarm_i2c_info1));
+       if (err < 0)
+               printk(KERN_ERR
+                      "swarm-i2c: cannot register board I2C devices\n");
+       return err;
+}
+
+arch_initcall(swarm_i2c_init);
index 35812823787bd7030f1cdc2452f923a9e06641a8..eb8f72ca02f45cfe954da3a1240e5a18fdd5d2bd 100644 (file)
@@ -320,7 +320,7 @@ static int try_address(struct i2c_adapter *i2c_adap,
                       unsigned char addr, int retries)
 {
        struct i2c_algo_bit_data *adap = i2c_adap->algo_data;
-       int i, ret = -1;
+       int i, ret = 0;
 
        for (i = 0; i <= retries; i++) {
                ret = i2c_outb(i2c_adap, addr);
@@ -508,7 +508,7 @@ static int bit_doAddress(struct i2c_adapter *i2c_adap, struct i2c_msg *msg)
                        addr ^= 1;
                ret = try_address(i2c_adap, addr, retries);
                if ((ret != 1) && !nak_ok)
-                       return -EREMOTEIO;
+                       return -ENXIO;
        }
 
        return 0;
index e954a20b97a647e1b5766d345117cab121a42811..d50b329a3c94f079a78c6f2c85bff7b2271d2ae0 100644 (file)
@@ -182,7 +182,7 @@ static int pca_xfer(struct i2c_adapter *i2c_adap,
        }
        if (state != 0xf8) {
                dev_dbg(&i2c_adap->dev, "bus is not idle. status is %#04x\n", state);
-               return -EIO;
+               return -EAGAIN;
        }
 
        DEB1("{{{ XFER %d messages\n", num);
index 8907b0191677e73b7ef6358fe9d8c937e8e49326..1e328d19cd6dd9aaf79573a7521f96579ff7cf0b 100644 (file)
@@ -78,6 +78,36 @@ static void i2c_stop(struct i2c_algo_pcf_data *adap)
        set_pcf(adap, 1, I2C_PCF_STOP);
 }
 
+static void handle_lab(struct i2c_algo_pcf_data *adap, const int *status)
+{
+       DEB2(printk(KERN_INFO
+               "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
+                *status));
+
+       /* Cleanup from LAB -- reset and enable ESO.
+        * This resets the PCF8584; since we've lost the bus, no
+        * further attempts should be made by callers to clean up
+        * (no i2c_stop() etc.)
+        */
+       set_pcf(adap, 1, I2C_PCF_PIN);
+       set_pcf(adap, 1, I2C_PCF_ESO);
+
+       /* We pause for a time period sufficient for any running
+        * I2C transaction to complete -- the arbitration logic won't
+        * work properly until the next START is seen.
+        * It is assumed the bus driver or client has set a proper value.
+        *
+        * REVISIT: should probably use msleep instead of mdelay if we
+        * know we can sleep.
+        */
+       if (adap->lab_mdelay)
+               mdelay(adap->lab_mdelay);
+
+       DEB2(printk(KERN_INFO
+               "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n",
+               get_pcf(adap, 1)));
+}
+
 static int wait_for_bb(struct i2c_algo_pcf_data *adap) {
 
        int timeout = DEF_TIMEOUT;
@@ -109,23 +139,7 @@ static int wait_for_pin(struct i2c_algo_pcf_data *adap, int *status) {
                *status = get_pcf(adap, 1);
        }
        if (*status & I2C_PCF_LAB) {
-               DEB2(printk(KERN_INFO 
-                       "i2c-algo-pcf.o: lost arbitration (CSR 0x%02x)\n",
-                        *status));
-               /* Cleanup from LAB-- reset and enable ESO.
-                * This resets the PCF8584; since we've lost the bus, no
-                * further attempts should be made by callers to clean up 
-                * (no i2c_stop() etc.)
-                */
-               set_pcf(adap, 1, I2C_PCF_PIN);
-               set_pcf(adap, 1, I2C_PCF_ESO);
-               /* TODO: we should pause for a time period sufficient for any
-                * running I2C transaction to complete-- the arbitration
-                * logic won't work properly until the next START is seen.
-                */
-               DEB2(printk(KERN_INFO 
-                       "i2c-algo-pcf.o: reset LAB condition (CSR 0x%02x)\n", 
-                       get_pcf(adap,1)));
+               handle_lab(adap, status);
                return(-EINTR);
        }
 #endif
index 48438cc5d0caa282bcf8ae7050bdbebccea3e879..6ee997b2817c450b3ac2fae2bf32e5ad035ff5d3 100644 (file)
@@ -4,6 +4,9 @@
 
 menu "I2C Hardware Bus support"
 
+comment "PC SMBus host controller drivers"
+       depends on PCI
+
 config I2C_ALI1535
        tristate "ALI 1535"
        depends on PCI
@@ -73,94 +76,6 @@ config I2C_AMD8111
          This driver can also be built as a module.  If so, the module
          will be called i2c-amd8111.
 
-config I2C_AT91
-       tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
-       depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
-       help
-         This supports the use of the I2C interface on Atmel AT91
-         processors.
-
-         This driver is BROKEN because the controller which it uses
-         will easily trigger RX overrun and TX underrun errors.  Using
-         low I2C clock rates may partially work around those issues
-         on some systems.  Another serious problem is that there is no
-         documented way to issue repeated START conditions, as needed
-         to support combined I2C messages.  Use the i2c-gpio driver
-         unless your system can cope with those limitations.
-
-config I2C_AU1550
-       tristate "Au1550/Au1200 SMBus interface"
-       depends on SOC_AU1550 || SOC_AU1200
-       help
-         If you say yes to this option, support will be included for the
-         Au1550 and Au1200 SMBus interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-au1550.
-
-config I2C_BLACKFIN_TWI
-       tristate "Blackfin TWI I2C support"
-       depends on BLACKFIN
-       help
-         This is the TWI I2C device driver for Blackfin BF522, BF525,
-         BF527, BF534, BF536, BF537 and BF54x. For other Blackfin processors,
-         please don't use this driver.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-bfin-twi.
-
-config I2C_BLACKFIN_TWI_CLK_KHZ
-       int "Blackfin TWI I2C clock (kHz)"
-       depends on I2C_BLACKFIN_TWI
-       range 10 400
-       default 50
-       help
-         The unit of the TWI clock is kHz.
-
-config I2C_DAVINCI
-       tristate "DaVinci I2C driver"
-       depends on ARCH_DAVINCI
-       help
-         Support for TI DaVinci I2C controller driver.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-davinci.
-
-         Please note that this driver might be needed to bring up other
-         devices such as DaVinci NIC.
-         For details please see http://www.ti.com/davinci
-
-config I2C_ELEKTOR
-       tristate "Elektor ISA card"
-       depends on ISA && BROKEN_ON_SMP
-       select I2C_ALGOPCF
-       help
-         This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
-         such an adapter.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-elektor.
-
-config I2C_GPIO
-       tristate "GPIO-based bitbanging I2C"
-       depends on GENERIC_GPIO
-       select I2C_ALGOBIT
-       help
-         This is a very simple bitbanging I2C driver utilizing the
-         arch-neutral GPIO API to control the SCL and SDA lines.
-
-config I2C_HYDRA
-       tristate "CHRP Apple Hydra Mac I/O I2C interface"
-       depends on PCI && PPC_CHRP && EXPERIMENTAL
-       select I2C_ALGOBIT
-       help
-         This supports the use of the I2C interface in the Apple Hydra Mac
-         I/O chip on some CHRP machines (e.g. the LongTrail).  Say Y if you
-         have such a machine.
-
-         This support is also available as a module.  If so, the module
-         will be called i2c-hydra.
-
 config I2C_I801
        tristate "Intel 82801 (ICH)"
        depends on PCI
@@ -186,41 +101,15 @@ config I2C_I801
          This driver can also be built as a module.  If so, the module
          will be called i2c-i801.
 
-config I2C_I810
-       tristate "Intel 810/815 (DEPRECATED)"
-       default n
+config I2C_ISCH
+       tristate "Intel SCH SMBus 1.0"
        depends on PCI
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for the Intel
-         810/815 family of mainboard I2C interfaces.  Specifically, the
-         following versions of the chipset are supported:
-           i810AA
-           i810AB
-           i810E
-           i815
-           i845G
-
-         This driver is deprecated in favor of the i810fb and intelfb drivers.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-i810.
-
-config I2C_PXA
-       tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
-       depends on EXPERIMENTAL && ARCH_PXA
        help
-         If you have devices in the PXA I2C bus, say yes to this option.
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pxa.
+         Say Y here if you want to use SMBus controller on the Intel SCH
+         based systems.
 
-config I2C_PXA_SLAVE
-       bool "Intel PXA2XX I2C Slave comms support"
-       depends on I2C_PXA
-       help
-         Support I2C slave mode communications on the PXA I2C bus.  This
-         is necessary for systems where the PXA may be a target on the
-         I2C bus.
+         This driver can also be built as a module. If so, the module
+         will be called i2c-isch.
 
 config I2C_PIIX4
        tristate "Intel PIIX4 and compatible (ATI/Serverworks/Broadcom/SMSC)"
@@ -247,39 +136,111 @@ config I2C_PIIX4
          This driver can also be built as a module.  If so, the module
          will be called i2c-piix4.
 
-config I2C_IBM_IIC
-       tristate "IBM PPC 4xx on-chip I2C interface"
-       depends on 4xx
+config I2C_NFORCE2
+       tristate "Nvidia nForce2, nForce3 and nForce4"
+       depends on PCI
        help
-         Say Y here if you want to use IIC peripheral found on
-         embedded IBM PPC 4xx based systems.
+         If you say yes to this option, support will be included for the Nvidia
+         nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-ibm_iic.
+         will be called i2c-nforce2.
 
-config I2C_IOP3XX
-       tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
-       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
+config I2C_NFORCE2_S4985
+       tristate "SMBus multiplexing on the Tyan S4985"
+       depends on I2C_NFORCE2 && EXPERIMENTAL
        help
-         Say Y here if you want to use the IIC bus controller on
-         the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
+         Enabling this option will add specific SMBus support for the Tyan
+         S4985 motherboard.  On this 4-CPU board, the SMBus is multiplexed
+         over 4 different channels, where the various memory module EEPROMs
+         live.  Saying yes here will give you access to these in addition
+         to the trunk.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-iop3xx.
+         will be called i2c-nforce2-s4985.
 
-config I2C_IXP2000
-       tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
-       depends on ARCH_IXP2000
+config I2C_SIS5595
+       tristate "SiS 5595"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the
+         SiS5595 SMBus (a subset of I2C) interface.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sis5595.
+
+config I2C_SIS630
+       tristate "SiS 630/730"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the
+         SiS630 and SiS730 SMBus (a subset of I2C) interface.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sis630.
+
+config I2C_SIS96X
+       tristate "SiS 96x"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the SiS
+         96x SMBus (a subset of I2C) interfaces.  Specifically, the following
+         chipsets are supported:
+           645/961
+           645DX/961
+           645DX/962
+           648/961
+           650/961
+           735
+           745
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sis96x.
+
+config I2C_VIA
+       tristate "VIA VT82C586B"
+       depends on PCI && EXPERIMENTAL
        select I2C_ALGOBIT
        help
-         Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
-         system and are using GPIO lines for an I2C bus.
+         If you say yes to this option, support will be included for the VIA
+          82C586B I2C interface
 
-         This support is also available as a module. If so, the module
-         will be called i2c-ixp2000.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-via.
 
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         instead.
+config I2C_VIAPRO
+       tristate "VIA VT82C596/82C686/82xx and CX700"
+       depends on PCI
+       help
+         If you say yes to this option, support will be included for the VIA
+         VT82C596 and later SMBus interface.  Specifically, the following
+         chipsets are supported:
+           VT82C596A/B
+           VT82C686A/B
+           VT8231
+           VT8233/A
+           VT8235
+           VT8237R/A/S
+           VT8251
+           CX700
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-viapro.
+
+comment "Mac SMBus host controller drivers"
+       depends on PPC_CHRP || PPC_PMAC
+
+config I2C_HYDRA
+       tristate "CHRP Apple Hydra Mac I/O I2C interface"
+       depends on PCI && PPC_CHRP && EXPERIMENTAL
+       select I2C_ALGOBIT
+       help
+         This supports the use of the I2C interface in the Apple Hydra Mac
+         I/O chip on some CHRP machines (e.g. the LongTrail).  Say Y if you
+         have such a machine.
+
+         This support is also available as a module.  If so, the module
+         will be called i2c-hydra.
 
 config I2C_POWERMAC
        tristate "Powermac I2C interface"
@@ -293,95 +254,158 @@ config I2C_POWERMAC
          This support is also available as a module.  If so, the module
          will be called i2c-powermac.
 
-config I2C_MPC
-       tristate "MPC107/824x/85xx/52xx/86xx"
-       depends on PPC32
+comment "I2C system bus drivers (mostly embedded / system-on-chip)"
+
+config I2C_AT91
+       tristate "Atmel AT91 I2C Two-Wire interface (TWI)"
+       depends on ARCH_AT91 && EXPERIMENTAL && BROKEN
        help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
-         MPC85xx/MPC8641 family processors. The driver may also work on 52xx
-         family processors, though interrupts are known not to work.
+         This supports the use of the I2C interface on Atmel AT91
+         processors.
 
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-mpc.
+         This driver is BROKEN because the controller which it uses
+         will easily trigger RX overrun and TX underrun errors.  Using
+         low I2C clock rates may partially work around those issues
+         on some systems.  Another serious problem is that there is no
+         documented way to issue repeated START conditions, as needed
+         to support combined I2C messages.  Use the i2c-gpio driver
+         unless your system can cope with those limitations.
 
-config I2C_NFORCE2
-       tristate "Nvidia nForce2, nForce3 and nForce4"
-       depends on PCI
+config I2C_AU1550
+       tristate "Au1550/Au1200 SMBus interface"
+       depends on SOC_AU1550 || SOC_AU1200
        help
-         If you say yes to this option, support will be included for the Nvidia
-         nForce2, nForce3 and nForce4 families of mainboard I2C interfaces.
+         If you say yes to this option, support will be included for the
+         Au1550 and Au1200 SMBus interface.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-nforce2.
+         will be called i2c-au1550.
 
-config I2C_OCORES
-       tristate "OpenCores I2C Controller"
-       depends on EXPERIMENTAL
+config I2C_BLACKFIN_TWI
+       tristate "Blackfin TWI I2C support"
+       depends on BLACKFIN
+       depends on !BF561 && !BF531 && !BF532 && !BF533
        help
-         If you say yes to this option, support will be included for the
-         OpenCores I2C controller. For details see
-         http://www.opencores.org/projects.cgi/web/i2c/overview
+         This is the I2C bus driver for Blackfin on-chip TWI interface.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-ocores.
+         will be called i2c-bfin-twi.
 
-config I2C_OMAP
-       tristate "OMAP I2C adapter"
-       depends on ARCH_OMAP
-       default y if MACH_OMAP_H3 || MACH_OMAP_OSK
+config I2C_BLACKFIN_TWI_CLK_KHZ
+       int "Blackfin TWI I2C clock (kHz)"
+       depends on I2C_BLACKFIN_TWI
+       range 10 400
+       default 50
        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.
+         The unit of the TWI clock is kHz.
 
-config I2C_PARPORT
-       tristate "Parallel port adapter"
-       depends on PARPORT
+config I2C_CPM
+       tristate "Freescale CPM1 or CPM2 (MPC8xx/826x)"
+       depends on (CPM1 || CPM2) && OF_I2C
+       help
+         This supports the use of the I2C interface on Freescale
+         processors with CPM1 or CPM2.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-cpm.
+
+config I2C_DAVINCI
+       tristate "DaVinci I2C driver"
+       depends on ARCH_DAVINCI
+       help
+         Support for TI DaVinci I2C controller driver.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-davinci.
+
+         Please note that this driver might be needed to bring up other
+         devices such as DaVinci NIC.
+         For details please see http://www.ti.com/davinci
+
+config I2C_GPIO
+       tristate "GPIO-based bitbanging I2C"
+       depends on GENERIC_GPIO
        select I2C_ALGOBIT
        help
-         This supports parallel port I2C adapters such as the ones made by
-         Philips or Velleman, Analog Devices evaluation boards, and more.
-         Basically any adapter using the parallel port as an I2C bus with
-         no extra chipset is supported by this driver, or could be.
+         This is a very simple bitbanging I2C driver utilizing the
+         arch-neutral GPIO API to control the SCL and SDA lines.
 
-         This driver is a replacement for (and was inspired by) an older
-         driver named i2c-philips-par.  The new driver supports more devices,
-         and makes it easier to add support for new devices.
+config I2C_IBM_IIC
+       tristate "IBM PPC 4xx on-chip I2C interface"
+       depends on 4xx
+       help
+         Say Y here if you want to use IIC peripheral found on
+         embedded IBM PPC 4xx based systems.
 
-         An adapter type parameter is now mandatory.  Please read the file
-         Documentation/i2c/busses/i2c-parport for details.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-ibm_iic.
 
-         Another driver exists, named i2c-parport-light, which doesn't depend
-         on the parport driver.  This is meant for embedded systems. Don't say
-         Y here if you intend to say Y or M there.
+config I2C_IOP3XX
+       tristate "Intel IOPx3xx and IXP4xx on-chip I2C interface"
+       depends on ARCH_IOP32X || ARCH_IOP33X || ARCH_IXP4XX || ARCH_IOP13XX
+       help
+         Say Y here if you want to use the IIC bus controller on
+         the Intel IOPx3xx I/O Processors or IXP4xx Network Processors.
 
-         This support is also available as a module.  If so, the module
-         will be called i2c-parport.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-iop3xx.
 
-config I2C_PARPORT_LIGHT
-       tristate "Parallel port adapter (light)"
+config I2C_IXP2000
+       tristate "IXP2000 GPIO-Based I2C Interface (DEPRECATED)"
+       depends on ARCH_IXP2000
        select I2C_ALGOBIT
        help
-         This supports parallel port I2C adapters such as the ones made by
-         Philips or Velleman, Analog Devices evaluation boards, and more.
-         Basically any adapter using the parallel port as an I2C bus with
-         no extra chipset is supported by this driver, or could be.
+         Say Y here if you have an Intel IXP2000 (2400, 2800, 2850) based
+         system and are using GPIO lines for an I2C bus.
 
-         This driver is a light version of i2c-parport.  It doesn't depend
-         on the parport driver, and uses direct I/O access instead.  This
-         might be preferred on embedded systems where wasting memory for
-         the clean but heavy parport handling is not an option.  The
-         drawback is a reduced portability and the impossibility to
-         daisy-chain other parallel port devices.
+         This support is also available as a module. If so, the module
+         will be called i2c-ixp2000.
 
-         Don't say Y here if you said Y or M to i2c-parport.  Saying M to
-         both is possible but both modules should not be loaded at the same
-         time.
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         instead.
 
-         This support is also available as a module.  If so, the module
-         will be called i2c-parport-light.
+config I2C_MPC
+       tristate "MPC107/824x/85xx/52xx/86xx"
+       depends on PPC32
+       help
+         If you say yes to this option, support will be included for the
+         built-in I2C interface on the MPC107/Tsi107/MPC8240/MPC8245 and
+         MPC85xx/MPC8641 family processors. The driver may also work on 52xx
+         family processors, though interrupts are known not to work.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mpc.
+
+config I2C_MV64XXX
+       tristate "Marvell mv64xxx I2C Controller"
+       depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
+       help
+         If you say yes to this option, support will be included for the
+         built-in I2C interface on the Marvell 64xxx line of host bridges.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-mv64xxx.
+
+config I2C_OCORES
+       tristate "OpenCores I2C Controller"
+       depends on EXPERIMENTAL
+       help
+         If you say yes to this option, support will be included for the
+         OpenCores I2C controller. For details see
+         http://www.opencores.org/projects.cgi/web/i2c/overview
+
+         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 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_PASEMI
        tristate "PA Semi SMBus interface"
@@ -389,23 +413,31 @@ config I2C_PASEMI
        help
          Supports the PA Semi PWRficient on-chip SMBus interfaces.
 
-config I2C_PROSAVAGE
-       tristate "S3/VIA (Pro)Savage (DEPRECATED)"
-       default n
-       depends on PCI
-       select I2C_ALGOBIT
+config I2C_PNX
+       tristate "I2C bus support for Philips PNX targets"
+       depends on ARCH_PNX4008
        help
-         If you say yes to this option, support will be included for the
-         I2C bus and DDC bus of the S3VIA embedded Savage4 and ProSavage8
-         graphics processors.
-         chipsets supported:
-           S3/VIA KM266/VT8375 aka ProSavage8
-           S3/VIA KM133/VT8365 aka Savage4
+         This driver supports the Philips IP3204 I2C IP block master and/or
+         slave controller
 
-         This driver is deprecated in favor of the savagefb driver.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-pnx.
 
-         This support is also available as a module.  If so, the module
-         will be called i2c-prosavage.
+config I2C_PXA
+       tristate "Intel PXA2XX I2C adapter (EXPERIMENTAL)"
+       depends on EXPERIMENTAL && ARCH_PXA
+       help
+         If you have devices in the PXA I2C bus, say yes to this option.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-pxa.
+
+config I2C_PXA_SLAVE
+       bool "Intel PXA2XX I2C Slave comms support"
+       depends on I2C_PXA
+       help
+         Support I2C slave mode communications on the PXA I2C bus.  This
+         is necessary for systems where the PXA may be a target on the
+         I2C bus.
 
 config I2C_S3C2410
        tristate "S3C2410 I2C Driver"
@@ -414,25 +446,24 @@ config I2C_S3C2410
          Say Y here to include support for I2C controller in the
          Samsung S3C2410 based System-on-Chip devices.
 
-config I2C_SAVAGE4
-       tristate "S3 Savage 4 (DEPRECATED)"
-       default n
-       depends on PCI
-       select I2C_ALGOBIT
+config I2C_SH7760
+       tristate "Renesas SH7760 I2C Controller"
+       depends on CPU_SUBTYPE_SH7760
        help
-         If you say yes to this option, support will be included for the
-         S3 Savage 4 I2C interface.
-
-         This driver is deprecated in favor of the savagefb driver.
+         This driver supports the 2 I2C interfaces on the Renesas SH7760.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-savage4.
+         will be called i2c-sh7760.
 
-config I2C_SIBYTE
-       tristate "SiByte SMBus interface"
-       depends on SIBYTE_SB1xxx_SOC
+config I2C_SH_MOBILE
+       tristate "SuperH Mobile I2C Controller"
+       depends on SUPERH
        help
-         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
+         If you say yes to this option, support will be included for the
+         built-in I2C interface on the Renesas SH-Mobile processor.
+
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-sh_mobile.
 
 config I2C_SIMTEC
        tristate "Simtec Generic I2C interface"
@@ -446,86 +477,65 @@ config I2C_SIMTEC
          This driver can also be built as a module. If so, the module
          will be called i2c-simtec.
 
-config SCx200_I2C
-       tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
-       depends on SCx200_GPIO
+config I2C_VERSATILE
+       tristate "ARM Versatile/Realview I2C bus support"
+       depends on ARCH_VERSATILE || ARCH_REALVIEW
        select I2C_ALGOBIT
        help
-         Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
-
-         If you don't know what to do here, say N.
+         Say yes if you want to support the I2C serial bus on ARMs Versatile
+         range of platforms.
 
-         This support is also available as a module.  If so, the module
-         will be called scx200_i2c.
+         This driver can also be built as a module.  If so, the module
+         will be called i2c-versatile.
 
-         This driver is deprecated and will be dropped soon. Use i2c-gpio
-         (or scx200_acb) instead.
+comment "External I2C/SMBus adapter drivers"
 
-config SCx200_I2C_SCL
-       int "GPIO pin used for SCL"
-       depends on SCx200_I2C
-       default "12"
+config I2C_PARPORT
+       tristate "Parallel port adapter"
+       depends on PARPORT
+       select I2C_ALGOBIT
        help
-         Enter the GPIO pin number used for the SCL signal.  This value can
-         also be specified with a module parameter.
+         This supports parallel port I2C adapters such as the ones made by
+         Philips or Velleman, Analog Devices evaluation boards, and more.
+         Basically any adapter using the parallel port as an I2C bus with
+         no extra chipset is supported by this driver, or could be.
 
-config SCx200_I2C_SDA
-       int "GPIO pin used for SDA"
-       depends on SCx200_I2C
-       default "13"
-       help
-         Enter the GPIO pin number used for the SSA signal.  This value can
-         also be specified with a module parameter.
+         This driver is a replacement for (and was inspired by) an older
+         driver named i2c-philips-par.  The new driver supports more devices,
+         and makes it easier to add support for new devices.
 
-config SCx200_ACB
-       tristate "Geode ACCESS.bus support"
-       depends on X86_32 && PCI
-       help
-         Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
-         SC1100 processors and the CS5535 and CS5536 Geode companion devices.
+         An adapter type parameter is now mandatory.  Please read the file
+         Documentation/i2c/busses/i2c-parport for details.
 
-         If you don't know what to do here, say N.
+         Another driver exists, named i2c-parport-light, which doesn't depend
+         on the parport driver.  This is meant for embedded systems. Don't say
+         Y here if you intend to say Y or M there.
 
          This support is also available as a module.  If so, the module
-         will be called scx200_acb.
-
-config I2C_SIS5595
-       tristate "SiS 5595"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the
-         SiS5595 SMBus (a subset of I2C) interface.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis5595.
+         will be called i2c-parport.
 
-config I2C_SIS630
-       tristate "SiS 630/730"
-       depends on PCI
+config I2C_PARPORT_LIGHT
+       tristate "Parallel port adapter (light)"
+       select I2C_ALGOBIT
        help
-         If you say yes to this option, support will be included for the
-         SiS630 and SiS730 SMBus (a subset of I2C) interface.
+         This supports parallel port I2C adapters such as the ones made by
+         Philips or Velleman, Analog Devices evaluation boards, and more.
+         Basically any adapter using the parallel port as an I2C bus with
+         no extra chipset is supported by this driver, or could be.
 
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis630.
+         This driver is a light version of i2c-parport.  It doesn't depend
+         on the parport driver, and uses direct I/O access instead.  This
+         might be preferred on embedded systems where wasting memory for
+         the clean but heavy parport handling is not an option.  The
+         drawback is a reduced portability and the impossibility to
+         daisy-chain other parallel port devices.
 
-config I2C_SIS96X
-       tristate "SiS 96x"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the SiS
-         96x SMBus (a subset of I2C) interfaces.  Specifically, the following
-         chipsets are supported:
-           645/961
-           645DX/961
-           645DX/962
-           648/961
-           650/961
-           735
-           745
+         Don't say Y here if you said Y or M to i2c-parport.  Saying M to
+         both is possible but both modules should not be loaded at the same
+         time.
 
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sis96x.
+         This support is also available as a module.  If so, the module
+         will be called i2c-parport-light.
 
 config I2C_TAOS_EVM
        tristate "TAOS evaluation module"
@@ -543,21 +553,8 @@ config I2C_TAOS_EVM
          This support is also available as a module.  If so, the module
          will be called i2c-taos-evm.
 
-config I2C_STUB
-       tristate "I2C/SMBus Test Stub"
-       depends on EXPERIMENTAL && m
-       default 'n'
-       help
-         This module may be useful to developers of SMBus client drivers,
-         especially for certain kinds of sensor chips.
-
-         If you do build this module, be sure to read the notes and warnings
-         in <file:Documentation/i2c/i2c-stub>.
-
-         If you don't know what to do here, definitely say N.
-
 config I2C_TINY_USB
-       tristate "I2C-Tiny-USB"
+       tristate "Tiny-USB adapter"
        depends on USB
        help
          If you say yes to this option, support will be included for the
@@ -567,16 +564,21 @@ config I2C_TINY_USB
          This driver can also be built as a module.  If so, the module
          will be called i2c-tiny-usb.
 
-config I2C_VERSATILE
-       tristate "ARM Versatile/Realview I2C bus support"
-       depends on ARCH_VERSATILE || ARCH_REALVIEW
+comment "Graphics adapter I2C/DDC channel drivers"
+       depends on PCI
+
+config I2C_VOODOO3
+       tristate "Voodoo 3"
+       depends on PCI
        select I2C_ALGOBIT
        help
-         Say yes if you want to support the I2C serial bus on ARMs Versatile
-         range of platforms.
+         If you say yes to this option, support will be included for the
+         Voodoo 3 I2C interface.
 
          This driver can also be built as a module.  If so, the module
-         will be called i2c-versatile.
+         will be called i2c-voodoo3.
+
+comment "Other I2C/SMBus bus drivers"
 
 config I2C_ACORN
        tristate "Acorn IOC/IOMD I2C bus support"
@@ -588,46 +590,16 @@ config I2C_ACORN
 
          If you don't know, say Y.
 
-config I2C_VIA
-       tristate "VIA 82C586B"
-       depends on PCI && EXPERIMENTAL
-       select I2C_ALGOBIT
-       help
-         If you say yes to this option, support will be included for the VIA
-          82C586B I2C interface
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-via.
-
-config I2C_VIAPRO
-       tristate "VIA VT82C596/82C686/82xx and CX700"
-       depends on PCI
-       help
-         If you say yes to this option, support will be included for the VIA
-         VT82C596 and later SMBus interface.  Specifically, the following
-         chipsets are supported:
-           VT82C596A/B
-           VT82C686A/B
-           VT8231
-           VT8233/A
-           VT8235
-           VT8237R/A/S
-           VT8251
-           CX700
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-viapro.
-
-config I2C_VOODOO3
-       tristate "Voodoo 3"
-       depends on PCI
-       select I2C_ALGOBIT
+config I2C_ELEKTOR
+       tristate "Elektor ISA card"
+       depends on ISA && BROKEN_ON_SMP
+       select I2C_ALGOPCF
        help
-         If you say yes to this option, support will be included for the
-         Voodoo 3 I2C interface.
+         This supports the PCF8584 ISA bus I2C adapter.  Say Y if you own
+         such an adapter.
 
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-voodoo3.
+         This support is also available as a module.  If so, the module
+         will be called i2c-elektor.
 
 config I2C_PCA_ISA
        tristate "PCA9564 on an ISA bus"
@@ -657,26 +629,6 @@ config I2C_PCA_PLATFORM
          This driver can also be built as a module.  If so, the module
          will be called i2c-pca-platform.
 
-config I2C_MV64XXX
-       tristate "Marvell mv64xxx I2C Controller"
-       depends on (MV64X60 || PLAT_ORION) && EXPERIMENTAL
-       help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the Marvell 64xxx line of host bridges.
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-mv64xxx.
-
-config I2C_PNX
-       tristate "I2C bus support for Philips PNX targets"
-       depends on ARCH_PNX4008
-       help
-         This driver supports the Philips IP3204 I2C IP block master and/or
-         slave controller
-
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-pnx.
-
 config I2C_PMCMSP
        tristate "PMC MSP I2C TWI Controller"
        depends on PMC_MSP
@@ -686,23 +638,66 @@ config I2C_PMCMSP
          This driver can also be built as module. If so, the module
          will be called i2c-pmcmsp.
 
-config I2C_SH7760
-       tristate "Renesas SH7760 I2C Controller"
-       depends on CPU_SUBTYPE_SH7760
+config I2C_SIBYTE
+       tristate "SiByte SMBus interface"
+       depends on SIBYTE_SB1xxx_SOC
        help
-         This driver supports the 2 I2C interfaces on the Renesas SH7760.
+         Supports the SiByte SOC on-chip I2C interfaces (2 channels).
 
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sh7760.
+config I2C_STUB
+       tristate "I2C/SMBus Test Stub"
+       depends on EXPERIMENTAL && m
+       default 'n'
+       help
+         This module may be useful to developers of SMBus client drivers,
+         especially for certain kinds of sensor chips.
 
-config I2C_SH_MOBILE
-       tristate "SuperH Mobile I2C Controller"
-       depends on SUPERH
+         If you do build this module, be sure to read the notes and warnings
+         in <file:Documentation/i2c/i2c-stub>.
+
+         If you don't know what to do here, definitely say N.
+
+config SCx200_I2C
+       tristate "NatSemi SCx200 I2C using GPIO pins (DEPRECATED)"
+       depends on SCx200_GPIO
+       select I2C_ALGOBIT
        help
-         If you say yes to this option, support will be included for the
-         built-in I2C interface on the Renesas SH-Mobile processor.
+         Enable the use of two GPIO pins of a SCx200 processor as an I2C bus.
 
-         This driver can also be built as a module.  If so, the module
-         will be called i2c-sh_mobile.
+         If you don't know what to do here, say N.
+
+         This support is also available as a module.  If so, the module
+         will be called scx200_i2c.
+
+         This driver is deprecated and will be dropped soon. Use i2c-gpio
+         (or scx200_acb) instead.
+
+config SCx200_I2C_SCL
+       int "GPIO pin used for SCL"
+       depends on SCx200_I2C
+       default "12"
+       help
+         Enter the GPIO pin number used for the SCL signal.  This value can
+         also be specified with a module parameter.
+
+config SCx200_I2C_SDA
+       int "GPIO pin used for SDA"
+       depends on SCx200_I2C
+       default "13"
+       help
+         Enter the GPIO pin number used for the SSA signal.  This value can
+         also be specified with a module parameter.
+
+config SCx200_ACB
+       tristate "Geode ACCESS.bus support"
+       depends on X86_32 && PCI
+       help
+         Enable the use of the ACCESS.bus controllers on the Geode SCx200 and
+         SC1100 processors and the CS5535 and CS5536 Geode companion devices.
+
+         If you don't know what to do here, say N.
+
+         This support is also available as a module.  If so, the module
+         will be called scx200_acb.
 
 endmenu
index e8c882a5ea666e5319b0725f3740b400e7223d4f..97dbfa2107fee2fe7b7170219c9aebf552b8381b 100644 (file)
@@ -2,57 +2,68 @@
 # Makefile for the i2c bus drivers.
 #
 
+# PC SMBus host controller drivers
 obj-$(CONFIG_I2C_ALI1535)      += i2c-ali1535.o
 obj-$(CONFIG_I2C_ALI1563)      += i2c-ali1563.o
 obj-$(CONFIG_I2C_ALI15X3)      += i2c-ali15x3.o
 obj-$(CONFIG_I2C_AMD756)       += i2c-amd756.o
 obj-$(CONFIG_I2C_AMD756_S4882) += i2c-amd756-s4882.o
 obj-$(CONFIG_I2C_AMD8111)      += i2c-amd8111.o
+obj-$(CONFIG_I2C_I801)         += i2c-i801.o
+obj-$(CONFIG_I2C_ISCH)         += i2c-isch.o
+obj-$(CONFIG_I2C_NFORCE2)      += i2c-nforce2.o
+obj-$(CONFIG_I2C_NFORCE2_S4985)        += i2c-nforce2-s4985.o
+obj-$(CONFIG_I2C_PIIX4)                += i2c-piix4.o
+obj-$(CONFIG_I2C_SIS5595)      += i2c-sis5595.o
+obj-$(CONFIG_I2C_SIS630)       += i2c-sis630.o
+obj-$(CONFIG_I2C_SIS96X)       += i2c-sis96x.o
+obj-$(CONFIG_I2C_VIA)          += i2c-via.o
+obj-$(CONFIG_I2C_VIAPRO)       += i2c-viapro.o
+
+# Mac SMBus host controller drivers
+obj-$(CONFIG_I2C_HYDRA)                += i2c-hydra.o
+obj-$(CONFIG_I2C_POWERMAC)     += i2c-powermac.o
+
+# Embebbed system I2C/SMBus host controller drivers
 obj-$(CONFIG_I2C_AT91)         += i2c-at91.o
 obj-$(CONFIG_I2C_AU1550)       += i2c-au1550.o
 obj-$(CONFIG_I2C_BLACKFIN_TWI) += i2c-bfin-twi.o
+obj-$(CONFIG_I2C_CPM)          += i2c-cpm.o
 obj-$(CONFIG_I2C_DAVINCI)      += i2c-davinci.o
-obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
 obj-$(CONFIG_I2C_GPIO)         += i2c-gpio.o
-obj-$(CONFIG_I2C_HYDRA)                += i2c-hydra.o
-obj-$(CONFIG_I2C_I801)         += i2c-i801.o
-obj-$(CONFIG_I2C_I810)         += i2c-i810.o
 obj-$(CONFIG_I2C_IBM_IIC)      += i2c-ibm_iic.o
 obj-$(CONFIG_I2C_IOP3XX)       += i2c-iop3xx.o
 obj-$(CONFIG_I2C_IXP2000)      += i2c-ixp2000.o
-obj-$(CONFIG_I2C_POWERMAC)     += i2c-powermac.o
 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_PASEMI)       += i2c-pasemi.o
-obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
-obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
-obj-$(CONFIG_I2C_PIIX4)                += i2c-piix4.o
-obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
 obj-$(CONFIG_I2C_PNX)          += i2c-pnx.o
-obj-$(CONFIG_I2C_PROSAVAGE)    += i2c-prosavage.o
 obj-$(CONFIG_I2C_PXA)          += i2c-pxa.o
 obj-$(CONFIG_I2C_S3C2410)      += i2c-s3c2410.o
-obj-$(CONFIG_I2C_SAVAGE4)      += i2c-savage4.o
 obj-$(CONFIG_I2C_SH7760)       += i2c-sh7760.o
 obj-$(CONFIG_I2C_SH_MOBILE)    += i2c-sh_mobile.o
-obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
 obj-$(CONFIG_I2C_SIMTEC)       += i2c-simtec.o
-obj-$(CONFIG_I2C_SIS5595)      += i2c-sis5595.o
-obj-$(CONFIG_I2C_SIS630)       += i2c-sis630.o
-obj-$(CONFIG_I2C_SIS96X)       += i2c-sis96x.o
-obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
+obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
+
+# External I2C/SMBus adapter drivers
+obj-$(CONFIG_I2C_PARPORT)      += i2c-parport.o
+obj-$(CONFIG_I2C_PARPORT_LIGHT)        += i2c-parport-light.o
 obj-$(CONFIG_I2C_TAOS_EVM)     += i2c-taos-evm.o
 obj-$(CONFIG_I2C_TINY_USB)     += i2c-tiny-usb.o
-obj-$(CONFIG_I2C_VERSATILE)    += i2c-versatile.o
-obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
-obj-$(CONFIG_I2C_VIA)          += i2c-via.o
-obj-$(CONFIG_I2C_VIAPRO)       += i2c-viapro.o
+
+# Graphics adapter I2C/DDC channel drivers
 obj-$(CONFIG_I2C_VOODOO3)      += i2c-voodoo3.o
+
+# Other I2C/SMBus bus drivers
+obj-$(CONFIG_I2C_ACORN)                += i2c-acorn.o
+obj-$(CONFIG_I2C_ELEKTOR)      += i2c-elektor.o
+obj-$(CONFIG_I2C_PCA_ISA)      += i2c-pca-isa.o
+obj-$(CONFIG_I2C_PCA_PLATFORM) += i2c-pca-platform.o
+obj-$(CONFIG_I2C_PMCMSP)       += i2c-pmcmsp.o
+obj-$(CONFIG_I2C_SIBYTE)       += i2c-sibyte.o
+obj-$(CONFIG_I2C_STUB)         += i2c-stub.o
 obj-$(CONFIG_SCx200_ACB)       += scx200_acb.o
 obj-$(CONFIG_SCx200_I2C)       += scx200_i2c.o
 
index f14372ac2fc5d08ef0b8ced5b994d86af7a5dee5..9cead9b9458e4770843ef25cc5fbf97ab158ab27 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    i2c-ali1535.c - Part of lm_sensors, Linux kernel modules for hardware
-                    monitoring
     Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, 
                         Philip Edelbrock <phil@netroedge.com>, 
                         Mark D. Studebaker <mdsxyz123@yahoo.com>,
@@ -61,6 +59,7 @@
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 
@@ -159,6 +158,11 @@ static int ali1535_setup(struct pci_dev *dev)
                goto exit;
        }
 
+       retval = acpi_check_region(ali1535_smba, ALI1535_SMB_IOSIZE,
+                                  ali1535_driver.name);
+       if (retval)
+               goto exit;
+
        if (!request_region(ali1535_smba, ALI1535_SMB_IOSIZE,
                            ali1535_driver.name)) {
                dev_err(&dev->dev, "ALI1535_smb region 0x%x already in use!\n",
@@ -259,7 +263,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
                        dev_err(&adap->dev,
                                "SMBus reset failed! (0x%02x) - controller or "
                                "device on bus is probably hung\n", temp);
-                       return -1;
+                       return -EBUSY;
                }
        } else {
                /* check and clear done bit */
@@ -281,12 +285,12 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
-               result = -1;
+               result = -ETIMEDOUT;
                dev_err(&adap->dev, "SMBus Timeout!\n");
        }
 
        if (temp & ALI1535_STS_FAIL) {
-               result = -1;
+               result = -EIO;
                dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
        }
 
@@ -295,7 +299,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
         * do a printk.  This means that bus collisions go unreported.
         */
        if (temp & ALI1535_STS_BUSERR) {
-               result = -1;
+               result = -ENXIO;
                dev_dbg(&adap->dev,
                        "Error: no response or bus collision ADD=%02x\n",
                        inb_p(SMBHSTADD));
@@ -303,13 +307,13 @@ static int ali1535_transaction(struct i2c_adapter *adap)
 
        /* haven't ever seen this */
        if (temp & ALI1535_STS_DEV) {
-               result = -1;
+               result = -EIO;
                dev_err(&adap->dev, "Error: device error\n");
        }
 
        /* check to see if the "command complete" indication is set */
        if (!(temp & ALI1535_STS_DONE)) {
-               result = -1;
+               result = -ETIMEDOUT;
                dev_err(&adap->dev, "Error: command never completed\n");
        }
 
@@ -332,7 +336,7 @@ static int ali1535_transaction(struct i2c_adapter *adap)
        return result;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
                          unsigned short flags, char read_write, u8 command,
                          int size, union i2c_smbus_data *data)
@@ -357,10 +361,6 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
        outb_p(0xFF, SMBHSTSTS);
 
        switch (size) {
-       case I2C_SMBUS_PROC_CALL:
-               dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-               result = -1;
-               goto EXIT;
        case I2C_SMBUS_QUICK:
                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
                       SMBHSTADD);
@@ -418,13 +418,15 @@ static s32 ali1535_access(struct i2c_adapter *adap, u16 addr,
                                outb_p(data->block[i], SMBBLKDAT);
                }
                break;
+       default:
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+               result = -EOPNOTSUPP;
+               goto EXIT;
        }
 
-       if (ali1535_transaction(adap)) {
-               /* Error in transaction */
-               result = -1;
+       result = ali1535_transaction(adap);
+       if (result)
                goto EXIT;
-       }
 
        if ((read_write == I2C_SMBUS_WRITE) || (size == ALI1535_QUICK)) {
                result = 0;
@@ -475,7 +477,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter ali1535_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_ALI1535,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
index 6b68074e518a072d1239c1e1f8ba61287cc4b456..fc3e5b026423d8e7ab752c73a93a2e18d1e975b5 100644 (file)
@@ -21,6 +21,7 @@
 #include <linux/i2c.h>
 #include <linux/pci.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 
 #define ALI1563_MAX_TIMEOUT    500
 #define        ALI1563_SMBBA           0x80
@@ -67,6 +68,7 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
 {
        u32 data;
        int timeout;
+       int status = -EIO;
 
        dev_dbg(&a->dev, "Transaction (pre): STS=%02x, CNTL1=%02x, "
                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
@@ -103,13 +105,15 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
                /* Issue 'kill' to host controller */
                outb_p(HST_CNTL2_KILL,SMB_HST_CNTL2);
                data = inb_p(SMB_HST_STS);
+               status = -ETIMEDOUT;
        }
 
        /* device error - no response, ignore the autodetection case */
-       if ((data & HST_STS_DEVERR) && (size != HST_CNTL2_QUICK)) {
-               dev_err(&a->dev, "Device error!\n");
+       if (data & HST_STS_DEVERR) {
+               if (size != HST_CNTL2_QUICK)
+                       dev_err(&a->dev, "Device error!\n");
+               status = -ENXIO;
        }
-
        /* bus collision */
        if (data & HST_STS_BUSERR) {
                dev_err(&a->dev, "Bus collision!\n");
@@ -122,13 +126,14 @@ static int ali1563_transaction(struct i2c_adapter * a, int size)
                outb_p(0x0,SMB_HST_CNTL2);
        }
 
-       return -1;
+       return status;
 }
 
 static int ali1563_block_start(struct i2c_adapter * a)
 {
        u32 data;
        int timeout;
+       int status = -EIO;
 
        dev_dbg(&a->dev, "Block (pre): STS=%02x, CNTL1=%02x, "
                "CNTL2=%02x, CMD=%02x, ADD=%02x, DAT0=%02x, DAT1=%02x\n",
@@ -164,13 +169,20 @@ static int ali1563_block_start(struct i2c_adapter * a)
 
        if (timeout && !(data & HST_STS_BAD))
                return 0;
+
+       if (timeout == 0)
+               status = -ETIMEDOUT;
+
+       if (data & HST_STS_DEVERR)
+               status = -ENXIO;
+
        dev_err(&a->dev, "SMBus Error: %s%s%s%s%s\n",
-               timeout ? "Timeout " : "",
+               timeout ? "" : "Timeout ",
                data & HST_STS_FAIL ? "Transaction Failed " : "",
                data & HST_STS_BUSERR ? "No response or Bus Collision " : "",
                data & HST_STS_DEVERR ? "Device Error " : "",
                !(data & HST_STS_DONE) ? "Transaction Never Finished " : "");
-       return -1;
+       return status;
 }
 
 static int ali1563_block(struct i2c_adapter * a, union i2c_smbus_data * data, u8 rw)
@@ -235,10 +247,6 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
 
        /* Map the size to what the chip understands */
        switch (size) {
-       case I2C_SMBUS_PROC_CALL:
-               dev_err(&a->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-               error = -EINVAL;
-               break;
        case I2C_SMBUS_QUICK:
                size = HST_CNTL2_QUICK;
                break;
@@ -254,6 +262,10 @@ static s32 ali1563_access(struct i2c_adapter * a, u16 addr,
        case I2C_SMBUS_BLOCK_DATA:
                size = HST_CNTL2_BLOCK;
                break;
+       default:
+               dev_warn(&a->dev, "Unsupported transaction %d\n", size);
+               error = -EOPNOTSUPP;
+               goto Done;
        }
 
        outb_p(((addr & 0x7f) << 1) | (rw & 0x01), SMB_HST_ADD);
@@ -345,6 +357,10 @@ static int __devinit ali1563_setup(struct pci_dev * dev)
                }
        }
 
+       if (acpi_check_region(ali1563_smba, ALI1563_SMB_IOSIZE,
+                             ali1563_pci_driver.name))
+               goto Err;
+
        if (!request_region(ali1563_smba, ALI1563_SMB_IOSIZE,
                            ali1563_pci_driver.name)) {
                dev_err(&dev->dev, "Could not allocate I/O space at 0x%04x\n",
@@ -371,7 +387,7 @@ static const struct i2c_algorithm ali1563_algorithm = {
 static struct i2c_adapter ali1563_adapter = {
        .owner  = THIS_MODULE,
        .id     = I2C_HW_SMBUS_ALI1563,
-       .class  = I2C_CLASS_HWMON,
+       .class  = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo   = &ali1563_algorithm,
 };
 
index 93bf87d709618fff0ba489aa17028b2d84a39f23..234fdde7d40e8712f7a0ce1d21d0cda09679737c 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    ali15x3.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
     Copyright (c) 1999  Frodo Looijaard <frodol@dds.nl> and
     Philip Edelbrock <phil@netroedge.com> and
     Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -68,6 +66,7 @@
 #include <linux/delay.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 /* ALI15X3 SMBus address offsets */
@@ -166,6 +165,10 @@ static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
        if(force_addr)
                ali15x3_smba = force_addr & ~(ALI15X3_SMB_IOSIZE - 1);
 
+       if (acpi_check_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
+                             ali15x3_driver.name))
+               return -EBUSY;
+
        if (!request_region(ali15x3_smba, ALI15X3_SMB_IOSIZE,
                            ali15x3_driver.name)) {
                dev_err(&ALI15X3_dev->dev,
@@ -282,7 +285,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
                        dev_err(&adap->dev, "SMBus reset failed! (0x%02x) - "
                                "controller or device on bus is probably hung\n",
                                temp);
-                       return -1;
+                       return -EBUSY;
                }
        } else {
                /* check and clear done bit */
@@ -304,12 +307,12 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
 
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
-               result = -1;
+               result = -ETIMEDOUT;
                dev_err(&adap->dev, "SMBus Timeout!\n");
        }
 
        if (temp & ALI15X3_STS_TERM) {
-               result = -1;
+               result = -EIO;
                dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
        }
 
@@ -320,7 +323,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
          This means that bus collisions go unreported.
        */
        if (temp & ALI15X3_STS_COLL) {
-               result = -1;
+               result = -ENXIO;
                dev_dbg(&adap->dev,
                        "Error: no response or bus collision ADD=%02x\n",
                        inb_p(SMBHSTADD));
@@ -328,7 +331,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
 
        /* haven't ever seen this */
        if (temp & ALI15X3_STS_DEV) {
-               result = -1;
+               result = -EIO;
                dev_err(&adap->dev, "Error: device error\n");
        }
        dev_dbg(&adap->dev, "Transaction (post): STS=%02x, CNT=%02x, CMD=%02x, "
@@ -338,7 +341,7 @@ static int ali15x3_transaction(struct i2c_adapter *adap)
        return result;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
                   unsigned short flags, char read_write, u8 command,
                   int size, union i2c_smbus_data * data)
@@ -362,9 +365,6 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
        }
 
        switch (size) {
-       case I2C_SMBUS_PROC_CALL:
-               dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-               return -1;
        case I2C_SMBUS_QUICK:
                outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
                       SMBHSTADD);
@@ -417,12 +417,16 @@ static s32 ali15x3_access(struct i2c_adapter * adap, u16 addr,
                }
                size = ALI15X3_BLOCK_DATA;
                break;
+       default:
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
        }
 
        outb_p(size, SMBHSTCNT);        /* output command */
 
-       if (ali15x3_transaction(adap))  /* Error in transaction */
-               return -1;
+       temp = ali15x3_transaction(adap);
+       if (temp)
+               return temp;
 
        if ((read_write == I2C_SMBUS_WRITE) || (size == ALI15X3_QUICK))
                return 0;
@@ -470,7 +474,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter ali15x3_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_ALI15X3,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
index c38a0a112208286787d94966f57048980ad459b8..2f150e33c74c9b19ae6f93dc6e1828ebd619d933 100644 (file)
@@ -58,7 +58,7 @@ static s32 amd756_access_virt0(struct i2c_adapter * adap, u16 addr,
        /* We exclude the multiplexed addresses */
        if (addr == 0x4c || (addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
         || addr == 0x18)
-               return -1;
+               return -ENXIO;
 
        mutex_lock(&amd756_lock);
 
@@ -86,7 +86,7 @@ static inline s32 amd756_access_channel(struct i2c_adapter * adap, u16 addr,
 
        /* We exclude the non-multiplexed addresses */
        if (addr != 0x4c && (addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
-               return -1;
+               return -ENXIO;
 
        mutex_lock(&amd756_lock);
 
index 43508d61eb7cf455c03fee1c82d4dfe501fbd260..1ea39254dac6e41dbd66fb0252d9016f1b95195d 100644 (file)
@@ -1,7 +1,4 @@
 /*
-    amd756.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
-
     Copyright (c) 1999-2002 Merlin Hughes <merlin@merlin.org>
 
     Shamelessly ripped from i2c-piix4.c:
@@ -45,6 +42,7 @@
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 /* AMD756 SMBus address offsets */
@@ -151,17 +149,17 @@ static int amd756_transaction(struct i2c_adapter *adap)
        }
 
        if (temp & GS_PRERR_STS) {
-               result = -1;
+               result = -ENXIO;
                dev_dbg(&adap->dev, "SMBus Protocol error (no response)!\n");
        }
 
        if (temp & GS_COL_STS) {
-               result = -1;
+               result = -EIO;
                dev_warn(&adap->dev, "SMBus collision!\n");
        }
 
        if (temp & GS_TO_STS) {
-               result = -1;
+               result = -ETIMEDOUT;
                dev_dbg(&adap->dev, "SMBus protocol timeout!\n");
        }
 
@@ -189,22 +187,18 @@ static int amd756_transaction(struct i2c_adapter *adap)
        outw_p(inw(SMB_GLOBAL_ENABLE) | GE_ABORT, SMB_GLOBAL_ENABLE);
        msleep(100);
        outw_p(GS_CLEAR_STS, SMB_GLOBAL_STATUS);
-       return -1;
+       return -EIO;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
                  unsigned short flags, char read_write,
                  u8 command, int size, union i2c_smbus_data * data)
 {
        int i, len;
+       int status;
 
-       /** TODO: Should I supporte the 10-bit transfers? */
        switch (size) {
-       case I2C_SMBUS_PROC_CALL:
-               dev_dbg(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-               /* TODO: Well... It is supported, I'm just not sure what to do here... */
-               return -1;
        case I2C_SMBUS_QUICK:
                outw_p(((addr & 0x7f) << 1) | (read_write & 0x01),
                       SMB_HOST_ADDRESS);
@@ -251,13 +245,17 @@ static s32 amd756_access(struct i2c_adapter * adap, u16 addr,
                }
                size = AMD756_BLOCK_DATA;
                break;
+       default:
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
        }
 
        /* How about enabling interrupts... */
        outw_p(size & GE_CYC_TYPE_MASK, SMB_GLOBAL_ENABLE);
 
-       if (amd756_transaction(adap))   /* Error in transaction */
-               return -1;
+       status = amd756_transaction(adap);
+       if (status)
+               return status;
 
        if ((read_write == I2C_SMBUS_WRITE) || (size == AMD756_QUICK))
                return 0;
@@ -301,7 +299,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 struct i2c_adapter amd756_smbus = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_AMD756,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
@@ -368,6 +366,11 @@ static int __devinit amd756_probe(struct pci_dev *pdev,
                amd756_ioport += SMB_ADDR_OFFSET;
        }
 
+       error = acpi_check_region(amd756_ioport, SMB_IOSIZE,
+                                 amd756_driver.name);
+       if (error)
+               return error;
+
        if (!request_region(amd756_ioport, SMB_IOSIZE, amd756_driver.name)) {
                dev_err(&pdev->dev, "SMB region 0x%x already in use!\n",
                        amd756_ioport);
index 5d1a27ef250450bc76457c8f34b48484beba5e54..3972208876b3d6f9671567fc3496eab12254df72 100644 (file)
@@ -16,6 +16,7 @@
 #include <linux/init.h>
 #include <linux/i2c.h>
 #include <linux/delay.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 MODULE_LICENSE("GPL");
@@ -77,7 +78,7 @@ static unsigned int amd_ec_wait_write(struct amd_smbus *smbus)
        if (!timeout) {
                dev_warn(&smbus->dev->dev,
                         "Timeout while waiting for IBF to clear\n");
-               return -1;
+               return -ETIMEDOUT;
        }
 
        return 0;
@@ -93,7 +94,7 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
        if (!timeout) {
                dev_warn(&smbus->dev->dev,
                         "Timeout while waiting for OBF to set\n");
-               return -1;
+               return -ETIMEDOUT;
        }
 
        return 0;
@@ -102,16 +103,21 @@ static unsigned int amd_ec_wait_read(struct amd_smbus *smbus)
 static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
                unsigned char *data)
 {
-       if (amd_ec_wait_write(smbus))
-               return -1;
+       int status;
+
+       status = amd_ec_wait_write(smbus);
+       if (status)
+               return status;
        outb(AMD_EC_CMD_RD, smbus->base + AMD_EC_CMD);
 
-       if (amd_ec_wait_write(smbus))
-               return -1;
+       status = amd_ec_wait_write(smbus);
+       if (status)
+               return status;
        outb(address, smbus->base + AMD_EC_DATA);
 
-       if (amd_ec_wait_read(smbus))
-               return -1;
+       status = amd_ec_wait_read(smbus);
+       if (status)
+               return status;
        *data = inb(smbus->base + AMD_EC_DATA);
 
        return 0;
@@ -120,16 +126,21 @@ static unsigned int amd_ec_read(struct amd_smbus *smbus, unsigned char address,
 static unsigned int amd_ec_write(struct amd_smbus *smbus, unsigned char address,
                unsigned char data)
 {
-       if (amd_ec_wait_write(smbus))
-               return -1;
+       int status;
+
+       status = amd_ec_wait_write(smbus);
+       if (status)
+               return status;
        outb(AMD_EC_CMD_WR, smbus->base + AMD_EC_CMD);
 
-       if (amd_ec_wait_write(smbus))
-               return -1;
+       status = amd_ec_wait_write(smbus);
+       if (status)
+               return status;
        outb(address, smbus->base + AMD_EC_DATA);
 
-       if (amd_ec_wait_write(smbus))
-               return -1;
+       status = amd_ec_wait_write(smbus);
+       if (status)
+               return status;
        outb(data, smbus->base + AMD_EC_DATA);
 
        return 0;
@@ -267,12 +278,17 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
 
                default:
                        dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
-                       return -1;
+                       return -EOPNOTSUPP;
        }
 
        amd_ec_write(smbus, AMD_SMB_ADDR, addr << 1);
        amd_ec_write(smbus, AMD_SMB_PRTCL, protocol);
 
+       /* FIXME this discards status from ec_read(); so temp[0] will
+        * hold stack garbage ... the rest of this routine will act
+        * nonsensically.  Ignored ec_write() status might explain
+        * some such failures...
+        */
        amd_ec_read(smbus, AMD_SMB_STS, temp + 0);
 
        if (~temp[0] & AMD_SMB_STS_DONE) {
@@ -286,7 +302,7 @@ static s32 amd8111_access(struct i2c_adapter * adap, u16 addr,
        }
 
        if ((~temp[0] & AMD_SMB_STS_DONE) || (temp[0] & AMD_SMB_STS_STATUS))
-               return -1;
+               return -EIO;
 
        if (read_write == I2C_SMBUS_WRITE)
                return 0;
@@ -359,6 +375,10 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
        smbus->base = pci_resource_start(dev, 0);
        smbus->size = pci_resource_len(dev, 0);
 
+       error = acpi_check_resource_conflict(&dev->resource[0]);
+       if (error)
+               goto out_kfree;
+
        if (!request_region(smbus->base, smbus->size, amd8111_driver.name)) {
                error = -EBUSY;
                goto out_kfree;
@@ -368,7 +388,7 @@ static int __devinit amd8111_probe(struct pci_dev *dev,
        snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
                "SMBus2 AMD8111 adapter at %04x", smbus->base);
        smbus->adapter.id = I2C_HW_SMBUS_AMD8111;
-       smbus->adapter.class = I2C_CLASS_HWMON;
+       smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        smbus->adapter.algo = &smbus_algorithm;
        smbus->adapter.algo_data = smbus;
 
index cae9dc89d88cc0737379cf38f1ce55116f1abbac..66a04c2c660fdfde8eec02110a47162d231d2021 100644 (file)
@@ -269,9 +269,13 @@ static int
 au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
 {
        struct i2c_au1550_data *adap = i2c_adap->algo_data;
+       volatile psc_smb_t *sp = (volatile psc_smb_t *)adap->psc_base;
        struct i2c_msg *p;
        int i, err = 0;
 
+       sp->psc_ctrl = PSC_CTRL_ENABLE;
+       au_sync();
+
        for (i = 0; !err && i < num; i++) {
                p = &msgs[i];
                err = do_address(adap, p->addr, p->flags & I2C_M_RD,
@@ -288,6 +292,10 @@ au1550_xfer(struct i2c_adapter *i2c_adap, struct i2c_msg *msgs, int num)
        */
        if (err == 0)
                err = num;
+
+       sp->psc_ctrl = PSC_CTRL_SUSPEND;
+       au_sync();
+
        return err;
 }
 
@@ -302,6 +310,61 @@ static const struct i2c_algorithm au1550_algo = {
        .functionality  = au1550_func,
 };
 
+static void i2c_au1550_setup(struct i2c_au1550_data *priv)
+{
+       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+       u32 stat;
+
+       sp->psc_ctrl = PSC_CTRL_DISABLE;
+       au_sync();
+       sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
+       sp->psc_smbcfg = 0;
+       au_sync();
+       sp->psc_ctrl = PSC_CTRL_ENABLE;
+       au_sync();
+       do {
+               stat = sp->psc_smbstat;
+               au_sync();
+       } while ((stat & PSC_SMBSTAT_SR) == 0);
+
+       sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
+                               PSC_SMBCFG_DD_DISABLE);
+
+       /* Divide by 8 to get a 6.25 MHz clock.  The later protocol
+        * timings are based on this clock.
+        */
+       sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
+       sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
+       au_sync();
+
+       /* Set the protocol timer values.  See Table 71 in the
+        * Au1550 Data Book for standard timing values.
+        */
+       sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
+               PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
+               PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
+               PSC_SMBTMR_SET_CH(15);
+       au_sync();
+
+       sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
+       do {
+               stat = sp->psc_smbstat;
+               au_sync();
+       } while ((stat & PSC_SMBSTAT_SR) == 0);
+
+       sp->psc_ctrl = PSC_CTRL_SUSPEND;
+       au_sync();
+}
+
+static void i2c_au1550_disable(struct i2c_au1550_data *priv)
+{
+       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
+
+       sp->psc_smbcfg = 0;
+       sp->psc_ctrl = PSC_CTRL_DISABLE;
+       au_sync();
+}
+
 /*
  * registering functions to load algorithms at runtime
  * Prior to calling us, the 50MHz clock frequency and routing
@@ -311,9 +374,7 @@ static int __devinit
 i2c_au1550_probe(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv;
-       volatile psc_smb_t *sp;
        struct resource *r;
-       u32 stat;
        int ret;
 
        r = platform_get_resource(pdev, IORESOURCE_MEM, 0);
@@ -348,43 +409,7 @@ i2c_au1550_probe(struct platform_device *pdev)
 
        /* Now, set up the PSC for SMBus PIO mode.
        */
-       sp = (volatile psc_smb_t *)priv->psc_base;
-       sp->psc_ctrl = PSC_CTRL_DISABLE;
-       au_sync();
-       sp->psc_sel = PSC_SEL_PS_SMBUSMODE;
-       sp->psc_smbcfg = 0;
-       au_sync();
-       sp->psc_ctrl = PSC_CTRL_ENABLE;
-       au_sync();
-       do {
-               stat = sp->psc_smbstat;
-               au_sync();
-       } while ((stat & PSC_SMBSTAT_SR) == 0);
-
-       sp->psc_smbcfg = (PSC_SMBCFG_RT_FIFO8 | PSC_SMBCFG_TT_FIFO8 |
-                               PSC_SMBCFG_DD_DISABLE);
-
-       /* Divide by 8 to get a 6.25 MHz clock.  The later protocol
-        * timings are based on this clock.
-        */
-       sp->psc_smbcfg |= PSC_SMBCFG_SET_DIV(PSC_SMBCFG_DIV8);
-       sp->psc_smbmsk = PSC_SMBMSK_ALLMASK;
-       au_sync();
-
-       /* Set the protocol timer values.  See Table 71 in the
-        * Au1550 Data Book for standard timing values.
-        */
-       sp->psc_smbtmr = PSC_SMBTMR_SET_TH(0) | PSC_SMBTMR_SET_PS(15) | \
-               PSC_SMBTMR_SET_PU(15) | PSC_SMBTMR_SET_SH(15) | \
-               PSC_SMBTMR_SET_SU(15) | PSC_SMBTMR_SET_CL(15) | \
-               PSC_SMBTMR_SET_CH(15);
-       au_sync();
-
-       sp->psc_smbcfg |= PSC_SMBCFG_DE_ENABLE;
-       do {
-               stat = sp->psc_smbstat;
-               au_sync();
-       } while ((stat & PSC_SMBSTAT_DR) == 0);
+       i2c_au1550_setup(priv);
 
        ret = i2c_add_numbered_adapter(&priv->adap);
        if (ret == 0) {
@@ -392,10 +417,7 @@ i2c_au1550_probe(struct platform_device *pdev)
                return 0;
        }
 
-       /* disable the PSC */
-       sp->psc_smbcfg = 0;
-       sp->psc_ctrl = PSC_CTRL_DISABLE;
-       au_sync();
+       i2c_au1550_disable(priv);
 
        release_resource(priv->ioarea);
        kfree(priv->ioarea);
@@ -409,27 +431,24 @@ static int __devexit
 i2c_au1550_remove(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
-       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
 
        platform_set_drvdata(pdev, NULL);
        i2c_del_adapter(&priv->adap);
-       sp->psc_smbcfg = 0;
-       sp->psc_ctrl = PSC_CTRL_DISABLE;
-       au_sync();
+       i2c_au1550_disable(priv);
        release_resource(priv->ioarea);
        kfree(priv->ioarea);
        kfree(priv);
        return 0;
 }
 
+#ifdef CONFIG_PM
 static int
 i2c_au1550_suspend(struct platform_device *pdev, pm_message_t state)
 {
        struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
-       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
 
-       sp->psc_ctrl = PSC_CTRL_SUSPEND;
-       au_sync();
+       i2c_au1550_disable(priv);
+
        return 0;
 }
 
@@ -437,14 +456,15 @@ static int
 i2c_au1550_resume(struct platform_device *pdev)
 {
        struct i2c_au1550_data *priv = platform_get_drvdata(pdev);
-       volatile psc_smb_t *sp = (volatile psc_smb_t *)priv->psc_base;
 
-       sp->psc_ctrl = PSC_CTRL_ENABLE;
-       au_sync();
-       while (!(sp->psc_smbstat & PSC_SMBSTAT_SR))
-               au_sync();
+       i2c_au1550_setup(priv);
+
        return 0;
 }
+#else
+#define i2c_au1550_suspend     NULL
+#define i2c_au1550_resume      NULL
+#endif
 
 static struct platform_driver au1xpsc_smbus_driver = {
        .driver = {
diff --git a/drivers/i2c/busses/i2c-cpm.c b/drivers/i2c/busses/i2c-cpm.c
new file mode 100644 (file)
index 0000000..8164de1
--- /dev/null
@@ -0,0 +1,745 @@
+/*
+ * Freescale CPM1/CPM2 I2C interface.
+ * Copyright (c) 1999 Dan Malek (dmalek@jlc.net).
+ *
+ * moved into proper i2c interface;
+ * Brad Parker (brad@heeltoe.com)
+ *
+ * Parts from dbox2_i2c.c (cvs.tuxbox.org)
+ * (C) 2000-2001 Felix Domke (tmbinc@gmx.net), Gillem (htoa@gmx.net)
+ *
+ * (C) 2007 Montavista Software, Inc.
+ * Vitaly Bordug <vitb@kernel.crashing.org>
+ *
+ * Converted to of_platform_device. Renamed to i2c-cpm.c.
+ * (C) 2007,2008 Jochen Friedrich <jochen@scram.de>
+ *
+ *  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/kernel.h>
+#include <linux/module.h>
+#include <linux/delay.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/interrupt.h>
+#include <linux/errno.h>
+#include <linux/stddef.h>
+#include <linux/i2c.h>
+#include <linux/io.h>
+#include <linux/dma-mapping.h>
+#include <linux/of_device.h>
+#include <linux/of_platform.h>
+#include <linux/of_i2c.h>
+#include <sysdev/fsl_soc.h>
+#include <asm/cpm.h>
+
+/* Try to define this if you have an older CPU (earlier than rev D4) */
+/* However, better use a GPIO based bitbang driver in this case :/   */
+#undef I2C_CHIP_ERRATA
+
+#define CPM_MAX_READ    513
+#define CPM_MAXBD       4
+
+#define I2C_EB                 (0x10) /* Big endian mode */
+#define I2C_EB_CPM2            (0x30) /* Big endian mode, memory snoop */
+
+#define DPRAM_BASE             ((u8 __iomem __force *)cpm_muram_addr(0))
+
+/* I2C parameter RAM. */
+struct i2c_ram {
+       ushort  rbase;          /* Rx Buffer descriptor base address */
+       ushort  tbase;          /* Tx Buffer descriptor base address */
+       u_char  rfcr;           /* Rx function code */
+       u_char  tfcr;           /* Tx function code */
+       ushort  mrblr;          /* Max receive buffer length */
+       uint    rstate;         /* Internal */
+       uint    rdp;            /* Internal */
+       ushort  rbptr;          /* Rx Buffer descriptor pointer */
+       ushort  rbc;            /* Internal */
+       uint    rxtmp;          /* Internal */
+       uint    tstate;         /* Internal */
+       uint    tdp;            /* Internal */
+       ushort  tbptr;          /* Tx Buffer descriptor pointer */
+       ushort  tbc;            /* Internal */
+       uint    txtmp;          /* Internal */
+       char    res1[4];        /* Reserved */
+       ushort  rpbase;         /* Relocation pointer */
+       char    res2[2];        /* Reserved */
+};
+
+#define I2COM_START    0x80
+#define I2COM_MASTER   0x01
+#define I2CER_TXE      0x10
+#define I2CER_BUSY     0x04
+#define I2CER_TXB      0x02
+#define I2CER_RXB      0x01
+#define I2MOD_EN       0x01
+
+/* I2C Registers */
+struct i2c_reg {
+       u8      i2mod;
+       u8      res1[3];
+       u8      i2add;
+       u8      res2[3];
+       u8      i2brg;
+       u8      res3[3];
+       u8      i2com;
+       u8      res4[3];
+       u8      i2cer;
+       u8      res5[3];
+       u8      i2cmr;
+};
+
+struct cpm_i2c {
+       char *base;
+       struct of_device *ofdev;
+       struct i2c_adapter adap;
+       uint dp_addr;
+       int version; /* CPM1=1, CPM2=2 */
+       int irq;
+       int cp_command;
+       int freq;
+       struct i2c_reg __iomem *i2c_reg;
+       struct i2c_ram __iomem *i2c_ram;
+       u16 i2c_addr;
+       wait_queue_head_t i2c_wait;
+       cbd_t __iomem *tbase;
+       cbd_t __iomem *rbase;
+       u_char *txbuf[CPM_MAXBD];
+       u_char *rxbuf[CPM_MAXBD];
+       u32 txdma[CPM_MAXBD];
+       u32 rxdma[CPM_MAXBD];
+};
+
+static irqreturn_t cpm_i2c_interrupt(int irq, void *dev_id)
+{
+       struct cpm_i2c *cpm;
+       struct i2c_reg __iomem *i2c_reg;
+       struct i2c_adapter *adap = dev_id;
+       int i;
+
+       cpm = i2c_get_adapdata(dev_id);
+       i2c_reg = cpm->i2c_reg;
+
+       /* Clear interrupt. */
+       i = in_8(&i2c_reg->i2cer);
+       out_8(&i2c_reg->i2cer, i);
+
+       dev_dbg(&adap->dev, "Interrupt: %x\n", i);
+
+       wake_up_interruptible(&cpm->i2c_wait);
+
+       return i ? IRQ_HANDLED : IRQ_NONE;
+}
+
+static void cpm_reset_i2c_params(struct cpm_i2c *cpm)
+{
+       struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
+
+       /* Set up the I2C parameters in the parameter ram. */
+       out_be16(&i2c_ram->tbase, (u8 __iomem *)cpm->tbase - DPRAM_BASE);
+       out_be16(&i2c_ram->rbase, (u8 __iomem *)cpm->rbase - DPRAM_BASE);
+
+       if (cpm->version == 1) {
+               out_8(&i2c_ram->tfcr, I2C_EB);
+               out_8(&i2c_ram->rfcr, I2C_EB);
+       } else {
+               out_8(&i2c_ram->tfcr, I2C_EB_CPM2);
+               out_8(&i2c_ram->rfcr, I2C_EB_CPM2);
+       }
+
+       out_be16(&i2c_ram->mrblr, CPM_MAX_READ);
+
+       out_be32(&i2c_ram->rstate, 0);
+       out_be32(&i2c_ram->rdp, 0);
+       out_be16(&i2c_ram->rbptr, 0);
+       out_be16(&i2c_ram->rbc, 0);
+       out_be32(&i2c_ram->rxtmp, 0);
+       out_be32(&i2c_ram->tstate, 0);
+       out_be32(&i2c_ram->tdp, 0);
+       out_be16(&i2c_ram->tbptr, 0);
+       out_be16(&i2c_ram->tbc, 0);
+       out_be32(&i2c_ram->txtmp, 0);
+}
+
+static void cpm_i2c_force_close(struct i2c_adapter *adap)
+{
+       struct cpm_i2c *cpm = i2c_get_adapdata(adap);
+       struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
+
+       dev_dbg(&adap->dev, "cpm_i2c_force_close()\n");
+
+       cpm_command(cpm->cp_command, CPM_CR_CLOSE_RX_BD);
+
+       out_8(&i2c_reg->i2cmr, 0x00);   /* Disable all interrupts */
+       out_8(&i2c_reg->i2cer, 0xff);
+}
+
+static void cpm_i2c_parse_message(struct i2c_adapter *adap,
+       struct i2c_msg *pmsg, int num, int tx, int rx)
+{
+       cbd_t __iomem *tbdf;
+       cbd_t __iomem *rbdf;
+       u_char addr;
+       u_char *tb;
+       u_char *rb;
+       struct cpm_i2c *cpm = i2c_get_adapdata(adap);
+
+       tbdf = cpm->tbase + tx;
+       rbdf = cpm->rbase + rx;
+
+       addr = pmsg->addr << 1;
+       if (pmsg->flags & I2C_M_RD)
+               addr |= 1;
+
+       tb = cpm->txbuf[tx];
+       rb = cpm->rxbuf[rx];
+
+       /* Align read buffer */
+       rb = (u_char *) (((ulong) rb + 1) & ~1);
+
+       tb[0] = addr;           /* Device address byte w/rw flag */
+
+       out_be16(&tbdf->cbd_datlen, pmsg->len + 1);
+       out_be16(&tbdf->cbd_sc, 0);
+
+       if (!(pmsg->flags & I2C_M_NOSTART))
+               setbits16(&tbdf->cbd_sc, BD_I2C_START);
+
+       if (tx + 1 == num)
+               setbits16(&tbdf->cbd_sc, BD_SC_LAST | BD_SC_WRAP);
+
+       if (pmsg->flags & I2C_M_RD) {
+               /*
+                * To read, we need an empty buffer of the proper length.
+                * All that is used is the first byte for address, the remainder
+                * is just used for timing (and doesn't really have to exist).
+                */
+
+               dev_dbg(&adap->dev, "cpm_i2c_read(abyte=0x%x)\n", addr);
+
+               out_be16(&rbdf->cbd_datlen, 0);
+               out_be16(&rbdf->cbd_sc, BD_SC_EMPTY | BD_SC_INTRPT);
+
+               if (rx + 1 == CPM_MAXBD)
+                       setbits16(&rbdf->cbd_sc, BD_SC_WRAP);
+
+               eieio();
+               setbits16(&tbdf->cbd_sc, BD_SC_READY);
+       } else {
+               dev_dbg(&adap->dev, "cpm_i2c_write(abyte=0x%x)\n", addr);
+
+               memcpy(tb+1, pmsg->buf, pmsg->len);
+
+               eieio();
+               setbits16(&tbdf->cbd_sc, BD_SC_READY | BD_SC_INTRPT);
+       }
+}
+
+static int cpm_i2c_check_message(struct i2c_adapter *adap,
+       struct i2c_msg *pmsg, int tx, int rx)
+{
+       cbd_t __iomem *tbdf;
+       cbd_t __iomem *rbdf;
+       u_char *tb;
+       u_char *rb;
+       struct cpm_i2c *cpm = i2c_get_adapdata(adap);
+
+       tbdf = cpm->tbase + tx;
+       rbdf = cpm->rbase + rx;
+
+       tb = cpm->txbuf[tx];
+       rb = cpm->rxbuf[rx];
+
+       /* Align read buffer */
+       rb = (u_char *) (((uint) rb + 1) & ~1);
+
+       eieio();
+       if (pmsg->flags & I2C_M_RD) {
+               dev_dbg(&adap->dev, "tx sc 0x%04x, rx sc 0x%04x\n",
+                       in_be16(&tbdf->cbd_sc), in_be16(&rbdf->cbd_sc));
+
+               if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) {
+                       dev_dbg(&adap->dev, "I2C read; No ack\n");
+                       return -ENXIO;
+               }
+               if (in_be16(&rbdf->cbd_sc) & BD_SC_EMPTY) {
+                       dev_err(&adap->dev,
+                               "I2C read; complete but rbuf empty\n");
+                       return -EREMOTEIO;
+               }
+               if (in_be16(&rbdf->cbd_sc) & BD_SC_OV) {
+                       dev_err(&adap->dev, "I2C read; Overrun\n");
+                       return -EREMOTEIO;
+               }
+               memcpy(pmsg->buf, rb, pmsg->len);
+       } else {
+               dev_dbg(&adap->dev, "tx sc %d 0x%04x\n", tx,
+                       in_be16(&tbdf->cbd_sc));
+
+               if (in_be16(&tbdf->cbd_sc) & BD_SC_NAK) {
+                       dev_dbg(&adap->dev, "I2C write; No ack\n");
+                       return -ENXIO;
+               }
+               if (in_be16(&tbdf->cbd_sc) & BD_SC_UN) {
+                       dev_err(&adap->dev, "I2C write; Underrun\n");
+                       return -EIO;
+               }
+               if (in_be16(&tbdf->cbd_sc) & BD_SC_CL) {
+                       dev_err(&adap->dev, "I2C write; Collision\n");
+                       return -EIO;
+               }
+       }
+       return 0;
+}
+
+static int cpm_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
+{
+       struct cpm_i2c *cpm = i2c_get_adapdata(adap);
+       struct i2c_reg __iomem *i2c_reg = cpm->i2c_reg;
+       struct i2c_ram __iomem *i2c_ram = cpm->i2c_ram;
+       struct i2c_msg *pmsg;
+       int ret, i;
+       int tptr;
+       int rptr;
+       cbd_t __iomem *tbdf;
+       cbd_t __iomem *rbdf;
+
+       if (num > CPM_MAXBD)
+               return -EINVAL;
+
+       /* Check if we have any oversized READ requests */
+       for (i = 0; i < num; i++) {
+               pmsg = &msgs[i];
+               if (pmsg->len >= CPM_MAX_READ)
+                       return -EINVAL;
+       }
+
+       /* Reset to use first buffer */
+       out_be16(&i2c_ram->rbptr, in_be16(&i2c_ram->rbase));
+       out_be16(&i2c_ram->tbptr, in_be16(&i2c_ram->tbase));
+
+       tbdf = cpm->tbase;
+       rbdf = cpm->rbase;
+
+       tptr = 0;
+       rptr = 0;
+
+       while (tptr < num) {
+               pmsg = &msgs[tptr];
+               dev_dbg(&adap->dev, "R: %d T: %d\n", rptr, tptr);
+
+               cpm_i2c_parse_message(adap, pmsg, num, tptr, rptr);
+               if (pmsg->flags & I2C_M_RD)
+                       rptr++;
+               tptr++;
+       }
+       /* Start transfer now */
+       /* Enable RX/TX/Error interupts */
+       out_8(&i2c_reg->i2cmr, I2CER_TXE | I2CER_TXB | I2CER_RXB);
+       out_8(&i2c_reg->i2cer, 0xff);   /* Clear interrupt status */
+       /* Chip bug, set enable here */
+       setbits8(&i2c_reg->i2mod, I2MOD_EN);    /* Enable */
+       /* Begin transmission */
+       setbits8(&i2c_reg->i2com, I2COM_START);
+
+       tptr = 0;
+       rptr = 0;
+
+       while (tptr < num) {
+               /* Check for outstanding messages */
+               dev_dbg(&adap->dev, "test ready.\n");
+               pmsg = &msgs[tptr];
+               if (pmsg->flags & I2C_M_RD)
+                       ret = wait_event_interruptible_timeout(cpm->i2c_wait,
+                               !(in_be16(&rbdf[rptr].cbd_sc) & BD_SC_EMPTY),
+                               1 * HZ);
+               else
+                       ret = wait_event_interruptible_timeout(cpm->i2c_wait,
+                               !(in_be16(&tbdf[tptr].cbd_sc) & BD_SC_READY),
+                               1 * HZ);
+               if (ret == 0) {
+                       ret = -EREMOTEIO;
+                       dev_err(&adap->dev, "I2C transfer: timeout\n");
+                       goto out_err;
+               }
+               if (ret > 0) {
+                       dev_dbg(&adap->dev, "ready.\n");
+                       ret = cpm_i2c_check_message(adap, pmsg, tptr, rptr);
+                       tptr++;
+                       if (pmsg->flags & I2C_M_RD)
+                               rptr++;
+                       if (ret)
+                               goto out_err;
+               }
+       }
+#ifdef I2C_CHIP_ERRATA
+       /*
+        * Chip errata, clear enable. This is not needed on rev D4 CPUs.
+        * Disabling I2C too early may cause too short stop condition
+        */
+       udelay(4);
+       clrbits8(&i2c_reg->i2mod, I2MOD_EN);
+#endif
+       return (num);
+
+out_err:
+       cpm_i2c_force_close(adap);
+#ifdef I2C_CHIP_ERRATA
+       /*
+        * Chip errata, clear enable. This is not needed on rev D4 CPUs.
+        */
+       clrbits8(&i2c_reg->i2mod, I2MOD_EN);
+#endif
+       return ret;
+}
+
+static u32 cpm_i2c_func(struct i2c_adapter *adap)
+{
+       return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
+}
+
+/* -----exported algorithm data: ------------------------------------- */
+
+static const struct i2c_algorithm cpm_i2c_algo = {
+       .master_xfer = cpm_i2c_xfer,
+       .functionality = cpm_i2c_func,
+};
+
+static const struct i2c_adapter cpm_ops = {
+       .owner          = THIS_MODULE,
+       .name           = "i2c-cpm",
+       .algo           = &cpm_i2c_algo,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+};
+
+static int __devinit cpm_i2c_setup(struct cpm_i2c *cpm)
+{
+       struct of_device *ofdev = cpm->ofdev;
+       const u32 *data;
+       int len, ret, i;
+       void __iomem *i2c_base;
+       cbd_t __iomem *tbdf;
+       cbd_t __iomem *rbdf;
+       unsigned char brg;
+
+       dev_dbg(&cpm->ofdev->dev, "cpm_i2c_setup()\n");
+
+       init_waitqueue_head(&cpm->i2c_wait);
+
+       cpm->irq = of_irq_to_resource(ofdev->node, 0, NULL);
+       if (cpm->irq == NO_IRQ)
+               return -EINVAL;
+
+       /* Install interrupt handler. */
+       ret = request_irq(cpm->irq, cpm_i2c_interrupt, 0, "cpm_i2c",
+                         &cpm->adap);
+       if (ret)
+               return ret;
+
+       /* I2C parameter RAM */
+       i2c_base = of_iomap(ofdev->node, 1);
+       if (i2c_base == NULL) {
+               ret = -EINVAL;
+               goto out_irq;
+       }
+
+       if (of_device_is_compatible(ofdev->node, "fsl,cpm1-i2c")) {
+
+               /* Check for and use a microcode relocation patch. */
+               cpm->i2c_ram = i2c_base;
+               cpm->i2c_addr = in_be16(&cpm->i2c_ram->rpbase);
+
+               /*
+                * Maybe should use cpm_muram_alloc instead of hardcoding
+                * this in micropatch.c
+                */
+               if (cpm->i2c_addr) {
+                       cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
+                       iounmap(i2c_base);
+               }
+
+               cpm->version = 1;
+
+       } else if (of_device_is_compatible(ofdev->node, "fsl,cpm2-i2c")) {
+               cpm->i2c_addr = cpm_muram_alloc(sizeof(struct i2c_ram), 64);
+               cpm->i2c_ram = cpm_muram_addr(cpm->i2c_addr);
+               out_be16(i2c_base, cpm->i2c_addr);
+               iounmap(i2c_base);
+
+               cpm->version = 2;
+
+       } else {
+               iounmap(i2c_base);
+               ret = -EINVAL;
+               goto out_irq;
+       }
+
+       /* I2C control/status registers */
+       cpm->i2c_reg = of_iomap(ofdev->node, 0);
+       if (cpm->i2c_reg == NULL) {
+               ret = -EINVAL;
+               goto out_ram;
+       }
+
+       data = of_get_property(ofdev->node, "fsl,cpm-command", &len);
+       if (!data || len != 4) {
+               ret = -EINVAL;
+               goto out_reg;
+       }
+       cpm->cp_command = *data;
+
+       data = of_get_property(ofdev->node, "linux,i2c-class", &len);
+       if (data && len == 4)
+               cpm->adap.class = *data;
+
+       data = of_get_property(ofdev->node, "clock-frequency", &len);
+       if (data && len == 4)
+               cpm->freq = *data;
+       else
+               cpm->freq = 60000; /* use 60kHz i2c clock by default */
+
+       /*
+        * Allocate space for CPM_MAXBD transmit and receive buffer
+        * descriptors in the DP ram.
+        */
+       cpm->dp_addr = cpm_muram_alloc(sizeof(cbd_t) * 2 * CPM_MAXBD, 8);
+       if (!cpm->dp_addr) {
+               ret = -ENOMEM;
+               goto out_reg;
+       }
+
+       cpm->tbase = cpm_muram_addr(cpm->dp_addr);
+       cpm->rbase = cpm_muram_addr(cpm->dp_addr + sizeof(cbd_t) * CPM_MAXBD);
+
+       /* Allocate TX and RX buffers */
+
+       tbdf = cpm->tbase;
+       rbdf = cpm->rbase;
+
+       for (i = 0; i < CPM_MAXBD; i++) {
+               cpm->rxbuf[i] = dma_alloc_coherent(
+                       NULL, CPM_MAX_READ + 1, &cpm->rxdma[i], GFP_KERNEL);
+               if (!cpm->rxbuf[i]) {
+                       ret = -ENOMEM;
+                       goto out_muram;
+               }
+               out_be32(&rbdf[i].cbd_bufaddr, ((cpm->rxdma[i] + 1) & ~1));
+
+               cpm->txbuf[i] = (unsigned char *)dma_alloc_coherent(
+                       NULL, CPM_MAX_READ + 1, &cpm->txdma[i], GFP_KERNEL);
+               if (!cpm->txbuf[i]) {
+                       ret = -ENOMEM;
+                       goto out_muram;
+               }
+               out_be32(&tbdf[i].cbd_bufaddr, cpm->txdma[i]);
+       }
+
+       /* Initialize Tx/Rx parameters. */
+
+       cpm_reset_i2c_params(cpm);
+
+       dev_dbg(&cpm->ofdev->dev, "i2c_ram 0x%p, i2c_addr 0x%04x, freq %d\n",
+               cpm->i2c_ram, cpm->i2c_addr, cpm->freq);
+       dev_dbg(&cpm->ofdev->dev, "tbase 0x%04x, rbase 0x%04x\n",
+               (u8 __iomem *)cpm->tbase - DPRAM_BASE,
+               (u8 __iomem *)cpm->rbase - DPRAM_BASE);
+
+       cpm_command(cpm->cp_command, CPM_CR_INIT_TRX);
+
+       /*
+        * Select an invalid address. Just make sure we don't use loopback mode
+        */
+       out_8(&cpm->i2c_reg->i2add, 0x7f << 1);
+
+       /*
+        * PDIV is set to 00 in i2mod, so brgclk/32 is used as input to the
+        * i2c baud rate generator. This is divided by 2 x (DIV + 3) to get
+        * the actual i2c bus frequency.
+        */
+       brg = get_brgfreq() / (32 * 2 * cpm->freq) - 3;
+       out_8(&cpm->i2c_reg->i2brg, brg);
+
+       out_8(&cpm->i2c_reg->i2mod, 0x00);
+       out_8(&cpm->i2c_reg->i2com, I2COM_MASTER);      /* Master mode */
+
+       /* Disable interrupts. */
+       out_8(&cpm->i2c_reg->i2cmr, 0);
+       out_8(&cpm->i2c_reg->i2cer, 0xff);
+
+       return 0;
+
+out_muram:
+       for (i = 0; i < CPM_MAXBD; i++) {
+               if (cpm->rxbuf[i])
+                       dma_free_coherent(NULL, CPM_MAX_READ + 1,
+                               cpm->rxbuf[i], cpm->rxdma[i]);
+               if (cpm->txbuf[i])
+                       dma_free_coherent(NULL, CPM_MAX_READ + 1,
+                               cpm->txbuf[i], cpm->txdma[i]);
+       }
+       cpm_muram_free(cpm->dp_addr);
+out_reg:
+       iounmap(cpm->i2c_reg);
+out_ram:
+       if ((cpm->version == 1) && (!cpm->i2c_addr))
+               iounmap(cpm->i2c_ram);
+       if (cpm->version == 2)
+               cpm_muram_free(cpm->i2c_addr);
+out_irq:
+       free_irq(cpm->irq, &cpm->adap);
+       return ret;
+}
+
+static void cpm_i2c_shutdown(struct cpm_i2c *cpm)
+{
+       int i;
+
+       /* Shut down I2C. */
+       clrbits8(&cpm->i2c_reg->i2mod, I2MOD_EN);
+
+       /* Disable interrupts */
+       out_8(&cpm->i2c_reg->i2cmr, 0);
+       out_8(&cpm->i2c_reg->i2cer, 0xff);
+
+       free_irq(cpm->irq, &cpm->adap);
+
+       /* Free all memory */
+       for (i = 0; i < CPM_MAXBD; i++) {
+               dma_free_coherent(NULL, CPM_MAX_READ + 1,
+                       cpm->rxbuf[i], cpm->rxdma[i]);
+               dma_free_coherent(NULL, CPM_MAX_READ + 1,
+                       cpm->txbuf[i], cpm->txdma[i]);
+       }
+
+       cpm_muram_free(cpm->dp_addr);
+       iounmap(cpm->i2c_reg);
+
+       if ((cpm->version == 1) && (!cpm->i2c_addr))
+               iounmap(cpm->i2c_ram);
+       if (cpm->version == 2)
+               cpm_muram_free(cpm->i2c_addr);
+}
+
+static int __devinit cpm_i2c_probe(struct of_device *ofdev,
+                        const struct of_device_id *match)
+{
+       int result, len;
+       struct cpm_i2c *cpm;
+       const u32 *data;
+
+       cpm = kzalloc(sizeof(struct cpm_i2c), GFP_KERNEL);
+       if (!cpm)
+               return -ENOMEM;
+
+       cpm->ofdev = ofdev;
+
+       dev_set_drvdata(&ofdev->dev, cpm);
+
+       cpm->adap = cpm_ops;
+       i2c_set_adapdata(&cpm->adap, cpm);
+       cpm->adap.dev.parent = &ofdev->dev;
+
+       result = cpm_i2c_setup(cpm);
+       if (result) {
+               dev_err(&ofdev->dev, "Unable to init hardware\n");
+               goto out_free;
+       }
+
+       /* register new adapter to i2c module... */
+
+       data = of_get_property(ofdev->node, "linux,i2c-index", &len);
+       if (data && len == 4) {
+               cpm->adap.nr = *data;
+               result = i2c_add_numbered_adapter(&cpm->adap);
+       } else
+               result = i2c_add_adapter(&cpm->adap);
+
+       if (result < 0) {
+               dev_err(&ofdev->dev, "Unable to register with I2C\n");
+               goto out_shut;
+       }
+
+       dev_dbg(&ofdev->dev, "hw routines for %s registered.\n",
+               cpm->adap.name);
+
+       /*
+        * register OF I2C devices
+        */
+       of_register_i2c_devices(&cpm->adap, ofdev->node);
+
+       return 0;
+out_shut:
+       cpm_i2c_shutdown(cpm);
+out_free:
+       dev_set_drvdata(&ofdev->dev, NULL);
+       kfree(cpm);
+
+       return result;
+}
+
+static int __devexit cpm_i2c_remove(struct of_device *ofdev)
+{
+       struct cpm_i2c *cpm = dev_get_drvdata(&ofdev->dev);
+
+       i2c_del_adapter(&cpm->adap);
+
+       cpm_i2c_shutdown(cpm);
+
+       dev_set_drvdata(&ofdev->dev, NULL);
+       kfree(cpm);
+
+       return 0;
+}
+
+static const struct of_device_id cpm_i2c_match[] = {
+       {
+               .compatible = "fsl,cpm1-i2c",
+       },
+       {
+               .compatible = "fsl,cpm2-i2c",
+       },
+       {},
+};
+
+MODULE_DEVICE_TABLE(of, cpm_i2c_match);
+
+static struct of_platform_driver cpm_i2c_driver = {
+       .match_table    = cpm_i2c_match,
+       .probe          = cpm_i2c_probe,
+       .remove         = __devexit_p(cpm_i2c_remove),
+       .driver         = {
+               .name   = "fsl-i2c-cpm",
+               .owner  = THIS_MODULE,
+       }
+};
+
+static int __init cpm_i2c_init(void)
+{
+       return of_register_platform_driver(&cpm_i2c_driver);
+}
+
+static void __exit cpm_i2c_exit(void)
+{
+       of_unregister_platform_driver(&cpm_i2c_driver);
+}
+
+module_init(cpm_i2c_init);
+module_exit(cpm_i2c_exit);
+
+MODULE_AUTHOR("Jochen Friedrich <jochen@scram.de>");
+MODULE_DESCRIPTION("I2C-Bus adapter routines for CPM boards");
+MODULE_LICENSE("GPL");
index 7ecbfc429b19722e4c681958f1fee5eab5b73c24..af3846eda9858e15bd233aa6fe3172333fac5971 100644 (file)
@@ -85,6 +85,7 @@
 #define DAVINCI_I2C_MDR_MST    (1 << 10)
 #define DAVINCI_I2C_MDR_TRX    (1 << 9)
 #define DAVINCI_I2C_MDR_XA     (1 << 8)
+#define DAVINCI_I2C_MDR_RM     (1 << 7)
 #define DAVINCI_I2C_MDR_IRS    (1 << 5)
 
 #define DAVINCI_I2C_IMR_AAS    (1 << 6)
@@ -112,6 +113,7 @@ struct davinci_i2c_dev {
        u8                      *buf;
        size_t                  buf_len;
        int                     irq;
+       u8                      terminate;
        struct i2c_adapter      adapter;
 };
 
@@ -142,6 +144,7 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
        struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
        u16 psc;
        u32 clk;
+       u32 d;
        u32 clkh;
        u32 clkl;
        u32 input_clock = clk_get_rate(dev->clk);
@@ -171,23 +174,29 @@ static int i2c_davinci_init(struct davinci_i2c_dev *dev)
         *       if PSC > 1 , d = 5
         */
 
-       psc = 26; /* To get 1MHz clock */
+       /* get minimum of 7 MHz clock, but max of 12 MHz */
+       psc = (input_clock / 7000000) - 1;
+       if ((input_clock / (psc + 1)) > 12000000)
+               psc++;  /* better to run under spec than over */
+       d = (psc >= 2) ? 5 : 7 - psc;
 
-       clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - 10;
-       clkh = (50 * clk) / 100;
+       clk = ((input_clock / (psc + 1)) / (pdata->bus_freq * 1000)) - (d << 1);
+       clkh = clk >> 1;
        clkl = clk - clkh;
 
        davinci_i2c_write_reg(dev, DAVINCI_I2C_PSC_REG, psc);
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKH_REG, clkh);
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CLKL_REG, clkl);
 
-       dev_dbg(dev->dev, "CLK  = %d\n", clk);
+       dev_dbg(dev->dev, "input_clock = %d, CLK = %d\n", input_clock, clk);
        dev_dbg(dev->dev, "PSC  = %d\n",
                davinci_i2c_read_reg(dev, DAVINCI_I2C_PSC_REG));
        dev_dbg(dev->dev, "CLKL = %d\n",
                davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKL_REG));
        dev_dbg(dev->dev, "CLKH = %d\n",
                davinci_i2c_read_reg(dev, DAVINCI_I2C_CLKH_REG));
+       dev_dbg(dev->dev, "bus_freq = %dkHz, bus_delay = %d\n",
+               pdata->bus_freq, pdata->bus_delay);
 
        /* Take the I2C module out of reset: */
        w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
@@ -233,7 +242,6 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
        struct davinci_i2c_dev *dev = i2c_get_adapdata(adap);
        struct davinci_i2c_platform_data *pdata = dev->dev->platform_data;
        u32 flag;
-       u32 stat;
        u16 w;
        int r;
 
@@ -254,12 +262,9 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
 
        davinci_i2c_write_reg(dev, DAVINCI_I2C_CNT_REG, dev->buf_len);
 
-       init_completion(&dev->cmd_complete);
+       INIT_COMPLETION(dev->cmd_complete);
        dev->cmd_err = 0;
 
-       /* Clear any pending interrupts by reading the IVR */
-       stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG);
-
        /* Take I2C out of reset, configure it as master and set the
         * start bit */
        flag = DAVINCI_I2C_MDR_IRS | DAVINCI_I2C_MDR_MST | DAVINCI_I2C_MDR_STT;
@@ -280,20 +285,34 @@ i2c_davinci_xfer_msg(struct i2c_adapter *adap, struct i2c_msg *msg, int stop)
                MOD_REG_BIT(w, DAVINCI_I2C_IMR_XRDY, 1);
        davinci_i2c_write_reg(dev, DAVINCI_I2C_IMR_REG, w);
 
+       dev->terminate = 0;
        /* write the data into mode register */
        davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, flag);
 
        r = wait_for_completion_interruptible_timeout(&dev->cmd_complete,
                                                      DAVINCI_I2C_TIMEOUT);
-       dev->buf_len = 0;
-       if (r < 0)
-               return r;
-
        if (r == 0) {
                dev_err(dev->dev, "controller timed out\n");
                i2c_davinci_init(dev);
+               dev->buf_len = 0;
                return -ETIMEDOUT;
        }
+       if (dev->buf_len) {
+               /* This should be 0 if all bytes were transferred
+                * or dev->cmd_err denotes an error.
+                * A signal may have aborted the transfer.
+                */
+               if (r >= 0) {
+                       dev_err(dev->dev, "abnormal termination buf_len=%i\n",
+                               dev->buf_len);
+                       r = -EREMOTEIO;
+               }
+               dev->terminate = 1;
+               wmb();
+               dev->buf_len = 0;
+       }
+       if (r < 0)
+               return r;
 
        /* no error */
        if (likely(!dev->cmd_err))
@@ -338,12 +357,11 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], int num)
 
        for (i = 0; i < num; i++) {
                ret = i2c_davinci_xfer_msg(adap, &msgs[i], (i == (num - 1)));
+               dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
+                       ret);
                if (ret < 0)
                        return ret;
        }
-
-       dev_dbg(dev->dev, "%s:%d ret: %d\n", __func__, __LINE__, ret);
-
        return num;
 }
 
@@ -352,6 +370,27 @@ static u32 i2c_davinci_func(struct i2c_adapter *adap)
        return I2C_FUNC_I2C | (I2C_FUNC_SMBUS_EMUL & ~I2C_FUNC_SMBUS_QUICK);
 }
 
+static void terminate_read(struct davinci_i2c_dev *dev)
+{
+       u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
+       w |= DAVINCI_I2C_MDR_NACK;
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
+
+       /* Throw away data */
+       davinci_i2c_read_reg(dev, DAVINCI_I2C_DRR_REG);
+       if (!dev->terminate)
+               dev_err(dev->dev, "RDR IRQ while no data requested\n");
+}
+static void terminate_write(struct davinci_i2c_dev *dev)
+{
+       u16 w = davinci_i2c_read_reg(dev, DAVINCI_I2C_MDR_REG);
+       w |= DAVINCI_I2C_MDR_RM | DAVINCI_I2C_MDR_STP;
+       davinci_i2c_write_reg(dev, DAVINCI_I2C_MDR_REG, w);
+
+       if (!dev->terminate)
+               dev_err(dev->dev, "TDR IRQ while no data to send\n");
+}
+
 /*
  * Interrupt service routine. This gets called whenever an I2C interrupt
  * occurs.
@@ -372,12 +411,15 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
 
                switch (stat) {
                case DAVINCI_I2C_IVR_AL:
+                       /* Arbitration lost, must retry */
                        dev->cmd_err |= DAVINCI_I2C_STR_AL;
+                       dev->buf_len = 0;
                        complete(&dev->cmd_complete);
                        break;
 
                case DAVINCI_I2C_IVR_NACK:
                        dev->cmd_err |= DAVINCI_I2C_STR_NACK;
+                       dev->buf_len = 0;
                        complete(&dev->cmd_complete);
                        break;
 
@@ -399,9 +441,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
                                davinci_i2c_write_reg(dev,
                                        DAVINCI_I2C_STR_REG,
                                        DAVINCI_I2C_IMR_RRDY);
-                       } else
-                               dev_err(dev->dev, "RDR IRQ while no "
-                                       "data requested\n");
+                       } else {
+                               /* signal can terminate transfer */
+                               terminate_read(dev);
+                       }
                        break;
 
                case DAVINCI_I2C_IVR_XRDY:
@@ -418,9 +461,10 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void *dev_id)
                                davinci_i2c_write_reg(dev,
                                                      DAVINCI_I2C_IMR_REG,
                                                      w);
-                       } else
-                               dev_err(dev->dev, "TDR IRQ while no data to "
-                                       "send\n");
+                       } else {
+                               /* signal can terminate transfer */
+                               terminate_write(dev);
+                       }
                        break;
 
                case DAVINCI_I2C_IVR_SCD:
@@ -475,6 +519,7 @@ static int davinci_i2c_probe(struct platform_device *pdev)
                goto err_release_region;
        }
 
+       init_completion(&dev->cmd_complete);
        dev->dev = get_device(&pdev->dev);
        dev->irq = irq->start;
        platform_set_drvdata(pdev, dev);
index b7a9977b025f31a492d632f8b57cb49930f05466..7f38c01fb3a06ce83753f4d411cde7f907f91086 100644 (file)
@@ -196,13 +196,11 @@ static struct i2c_algo_pcf_data pcf_isa_data = {
        .getown     = pcf_isa_getown,
        .getclock   = pcf_isa_getclock,
        .waitforpin = pcf_isa_waitforpin,
-       .udelay     = 10,
-       .timeout    = 100,
 };
 
 static struct i2c_adapter pcf_isa_ops = {
        .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .id             = I2C_HW_P_ELEK,
        .algo_data      = &pcf_isa_data,
        .name           = "i2c-elektor",
index 7c1b762aa681fc727312c0e0c1db08dbff0c2c04..79b455a1f090587c4c63d5b29b76d8474c81b122 100644 (file)
@@ -140,7 +140,7 @@ static int __init i2c_gpio_probe(struct platform_device *pdev)
        adap->owner = THIS_MODULE;
        snprintf(adap->name, sizeof(adap->name), "i2c-gpio%d", pdev->id);
        adap->algo_data = bit_data;
-       adap->class = I2C_CLASS_HWMON;
+       adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adap->dev.parent = &pdev->dev;
 
        /*
index f9972f9651e45f3497386cae1d16a55686066eab..1098f21ace133225901e65d13f9cb63a99c6359d 100644 (file)
@@ -1,7 +1,4 @@
 /*
-    i2c-hydra.c - Part of lm_sensors,  Linux kernel modules
-                  for hardware monitoring
-
     i2c Support for the Apple `Hydra' Mac I/O
 
     Copyright (c) 1999-2004 Geert Uytterhoeven <geert@linux-m68k.org>
index b0f771fe43265df51f425593fc1f42ee47ba058e..dc7ea32b69a8f64c3a09725cd54748fb8c95b9c8 100644 (file)
@@ -1,10 +1,8 @@
 /*
-    i2c-i801.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, and Mark D. Studebaker
     <mdsxyz123@yahoo.com>
-    Copyright (C) 2007         Jean Delvare <khali@linux-fr.org>
+    Copyright (C) 2007, 2008   Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -64,6 +62,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 /* I801 SMBus address offsets */
 #define SMBHSTSTS_INTR         0x02
 #define SMBHSTSTS_HOST_BUSY    0x01
 
+#define STATUS_FLAGS           (SMBHSTSTS_BYTE_DONE | SMBHSTSTS_FAILED | \
+                                SMBHSTSTS_BUS_ERR | SMBHSTSTS_DEV_ERR | \
+                                SMBHSTSTS_INTR)
+
 static unsigned long i801_smba;
 static unsigned char i801_original_hstcfg;
 static struct pci_driver i801_driver;
@@ -132,105 +135,137 @@ static struct pci_dev *I801_dev;
 #define FEATURE_I2C_BLOCK_READ (1 << 3)
 static unsigned int i801_features;
 
-static int i801_transaction(int xact)
+/* Make sure the SMBus host is ready to start transmitting.
+   Return 0 if it is, -EBUSY if it is not. */
+static int i801_check_pre(void)
 {
-       int temp;
-       int result = 0;
-       int timeout = 0;
+       int status;
 
-       dev_dbg(&I801_dev->dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
-               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
-               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
-               inb_p(SMBHSTDAT1));
-
-       /* Make sure the SMBus host is ready to start transmitting */
-       /* 0x1f = Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
-       if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
-               dev_dbg(&I801_dev->dev, "SMBus busy (%02x). Resetting...\n",
-                       temp);
-               outb_p(temp, SMBHSTSTS);
-               if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
-                       dev_dbg(&I801_dev->dev, "Failed! (%02x)\n", temp);
-                       return -1;
-               } else {
-                       dev_dbg(&I801_dev->dev, "Successful!\n");
+       status = inb_p(SMBHSTSTS);
+       if (status & SMBHSTSTS_HOST_BUSY) {
+               dev_err(&I801_dev->dev, "SMBus is busy, can't use it!\n");
+               return -EBUSY;
+       }
+
+       status &= STATUS_FLAGS;
+       if (status) {
+               dev_dbg(&I801_dev->dev, "Clearing status flags (%02x)\n",
+                       status);
+               outb_p(status, SMBHSTSTS);
+               status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
+               if (status) {
+                       dev_err(&I801_dev->dev,
+                               "Failed clearing status flags (%02x)\n",
+                               status);
+                       return -EBUSY;
                }
        }
 
-       /* the current contents of SMBHSTCNT can be overwritten, since PEC,
-        * INTREN, SMBSCMD are passed in xact */
-       outb_p(xact | I801_START, SMBHSTCNT);
+       return 0;
+}
 
-       /* We will always wait for a fraction of a second! */
-       do {
-               msleep(1);
-               temp = inb_p(SMBHSTSTS);
-       } while ((temp & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
+/* Convert the status register to an error code, and clear it. */
+static int i801_check_post(int status, int timeout)
+{
+       int result = 0;
 
        /* If the SMBus is still busy, we give up */
-       if (timeout >= MAX_TIMEOUT) {
-               dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
-               result = -1;
+       if (timeout) {
+               dev_err(&I801_dev->dev, "Transaction timeout\n");
                /* try to stop the current command */
                dev_dbg(&I801_dev->dev, "Terminating the current operation\n");
                outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
                msleep(1);
                outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL), SMBHSTCNT);
-       }
 
-       if (temp & SMBHSTSTS_FAILED) {
-               result = -1;
-               dev_dbg(&I801_dev->dev, "Error: Failed bus transaction\n");
+               /* Check if it worked */
+               status = inb_p(SMBHSTSTS);
+               if ((status & SMBHSTSTS_HOST_BUSY) ||
+                   !(status & SMBHSTSTS_FAILED))
+                       dev_err(&I801_dev->dev,
+                               "Failed terminating the transaction\n");
+               outb_p(STATUS_FLAGS, SMBHSTSTS);
+               return -ETIMEDOUT;
        }
 
-       if (temp & SMBHSTSTS_BUS_ERR) {
-               result = -1;
-               dev_err(&I801_dev->dev, "Bus collision! SMBus may be locked "
-                       "until next hard reset. (sorry!)\n");
-               /* Clock stops and slave is stuck in mid-transmission */
+       if (status & SMBHSTSTS_FAILED) {
+               result = -EIO;
+               dev_err(&I801_dev->dev, "Transaction failed\n");
        }
-
-       if (temp & SMBHSTSTS_DEV_ERR) {
-               result = -1;
-               dev_dbg(&I801_dev->dev, "Error: no response!\n");
+       if (status & SMBHSTSTS_DEV_ERR) {
+               result = -ENXIO;
+               dev_dbg(&I801_dev->dev, "No response\n");
+       }
+       if (status & SMBHSTSTS_BUS_ERR) {
+               result = -EAGAIN;
+               dev_dbg(&I801_dev->dev, "Lost arbitration\n");
        }
 
-       if ((inb_p(SMBHSTSTS) & 0x1f) != 0x00)
-               outb_p(inb(SMBHSTSTS), SMBHSTSTS);
-
-       if ((temp = (0x1f & inb_p(SMBHSTSTS))) != 0x00) {
-               dev_dbg(&I801_dev->dev, "Failed reset at end of transaction "
-                       "(%02x)\n", temp);
+       if (result) {
+               /* Clear error flags */
+               outb_p(status & STATUS_FLAGS, SMBHSTSTS);
+               status = inb_p(SMBHSTSTS) & STATUS_FLAGS;
+               if (status) {
+                       dev_warn(&I801_dev->dev, "Failed clearing status "
+                                "flags at end of transaction (%02x)\n",
+                                status);
+               }
        }
-       dev_dbg(&I801_dev->dev, "Transaction (post): CNT=%02x, CMD=%02x, "
-               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb_p(SMBHSTCNT),
-               inb_p(SMBHSTCMD), inb_p(SMBHSTADD), inb_p(SMBHSTDAT0),
-               inb_p(SMBHSTDAT1));
+
        return result;
 }
 
+static int i801_transaction(int xact)
+{
+       int status;
+       int result;
+       int timeout = 0;
+
+       result = i801_check_pre();
+       if (result < 0)
+               return result;
+
+       /* the current contents of SMBHSTCNT can be overwritten, since PEC,
+        * INTREN, SMBSCMD are passed in xact */
+       outb_p(xact | I801_START, SMBHSTCNT);
+
+       /* We will always wait for a fraction of a second! */
+       do {
+               msleep(1);
+               status = inb_p(SMBHSTSTS);
+       } while ((status & SMBHSTSTS_HOST_BUSY) && (timeout++ < MAX_TIMEOUT));
+
+       result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+       if (result < 0)
+               return result;
+
+       outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
+       return 0;
+}
+
 /* wait for INTR bit as advised by Intel */
 static void i801_wait_hwpec(void)
 {
        int timeout = 0;
-       int temp;
+       int status;
 
        do {
                msleep(1);
-               temp = inb_p(SMBHSTSTS);
-       } while ((!(temp & SMBHSTSTS_INTR))
+               status = inb_p(SMBHSTSTS);
+       } while ((!(status & SMBHSTSTS_INTR))
                 && (timeout++ < MAX_TIMEOUT));
 
        if (timeout >= MAX_TIMEOUT) {
                dev_dbg(&I801_dev->dev, "PEC Timeout!\n");
        }
-       outb_p(temp, SMBHSTSTS);
+       outb_p(status, SMBHSTSTS);
 }
 
 static int i801_block_transaction_by_block(union i2c_smbus_data *data,
                                           char read_write, int hwpec)
 {
        int i, len;
+       int status;
 
        inb_p(SMBHSTCNT); /* reset the data buffer index */
 
@@ -242,14 +277,15 @@ static int i801_block_transaction_by_block(union i2c_smbus_data *data,
                        outb_p(data->block[i+1], SMBBLKDAT);
        }
 
-       if (i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
-                            I801_PEC_EN * hwpec))
-               return -1;
+       status = i801_transaction(I801_BLOCK_DATA | ENABLE_INT9 |
+                                 I801_PEC_EN * hwpec);
+       if (status)
+               return status;
 
        if (read_write == I2C_SMBUS_READ) {
                len = inb_p(SMBHSTDAT0);
                if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
-                       return -1;
+                       return -EPROTO;
 
                data->block[0] = len;
                for (i = 0; i < len; i++)
@@ -264,10 +300,13 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
 {
        int i, len;
        int smbcmd;
-       int temp;
-       int result = 0;
+       int status;
+       int result;
        int timeout;
-       unsigned char errmask;
+
+       result = i801_check_pre();
+       if (result < 0)
+               return result;
 
        len = data->block[0];
 
@@ -291,36 +330,6 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
                }
                outb_p(smbcmd | ENABLE_INT9, SMBHSTCNT);
 
-               dev_dbg(&I801_dev->dev, "Block (pre %d): CNT=%02x, CMD=%02x, "
-                       "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
-                       inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
-                       inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
-
-               /* Make sure the SMBus host is ready to start transmitting */
-               temp = inb_p(SMBHSTSTS);
-               if (i == 1) {
-                       /* Erroneous conditions before transaction:
-                        * Byte_Done, Failed, Bus_Err, Dev_Err, Intr, Host_Busy */
-                       errmask = 0x9f;
-               } else {
-                       /* Erroneous conditions during transaction:
-                        * Failed, Bus_Err, Dev_Err, Intr */
-                       errmask = 0x1e;
-               }
-               if (temp & errmask) {
-                       dev_dbg(&I801_dev->dev, "SMBus busy (%02x). "
-                               "Resetting...\n", temp);
-                       outb_p(temp, SMBHSTSTS);
-                       if (((temp = inb_p(SMBHSTSTS)) & errmask) != 0x00) {
-                               dev_err(&I801_dev->dev,
-                                       "Reset failed! (%02x)\n", temp);
-                               return -1;
-                       }
-                       if (i != 1)
-                               /* if die in middle of block transaction, fail */
-                               return -1;
-               }
-
                if (i == 1)
                        outb_p(inb(SMBHSTCNT) | I801_START, SMBHSTCNT);
 
@@ -328,41 +337,28 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
                timeout = 0;
                do {
                        msleep(1);
-                       temp = inb_p(SMBHSTSTS);
+                       status = inb_p(SMBHSTSTS);
                }
-               while ((!(temp & SMBHSTSTS_BYTE_DONE))
+               while ((!(status & SMBHSTSTS_BYTE_DONE))
                       && (timeout++ < MAX_TIMEOUT));
 
-               /* If the SMBus is still busy, we give up */
-               if (timeout >= MAX_TIMEOUT) {
-                       /* try to stop the current command */
-                       dev_dbg(&I801_dev->dev, "Terminating the current "
-                                               "operation\n");
-                       outb_p(inb_p(SMBHSTCNT) | SMBHSTCNT_KILL, SMBHSTCNT);
-                       msleep(1);
-                       outb_p(inb_p(SMBHSTCNT) & (~SMBHSTCNT_KILL),
-                               SMBHSTCNT);
-                       result = -1;
-                       dev_dbg(&I801_dev->dev, "SMBus Timeout!\n");
-               }
-
-               if (temp & SMBHSTSTS_FAILED) {
-                       result = -1;
-                       dev_dbg(&I801_dev->dev,
-                               "Error: Failed bus transaction\n");
-               } else if (temp & SMBHSTSTS_BUS_ERR) {
-                       result = -1;
-                       dev_err(&I801_dev->dev, "Bus collision!\n");
-               } else if (temp & SMBHSTSTS_DEV_ERR) {
-                       result = -1;
-                       dev_dbg(&I801_dev->dev, "Error: no response!\n");
-               }
+               result = i801_check_post(status, timeout >= MAX_TIMEOUT);
+               if (result < 0)
+                       return result;
 
                if (i == 1 && read_write == I2C_SMBUS_READ
                 && command != I2C_SMBUS_I2C_BLOCK_DATA) {
                        len = inb_p(SMBHSTDAT0);
-                       if (len < 1 || len > I2C_SMBUS_BLOCK_MAX)
-                               return -1;
+                       if (len < 1 || len > I2C_SMBUS_BLOCK_MAX) {
+                               dev_err(&I801_dev->dev,
+                                       "Illegal SMBus block read size %d\n",
+                                       len);
+                               /* Recover */
+                               while (inb_p(SMBHSTSTS) & SMBHSTSTS_HOST_BUSY)
+                                       outb_p(SMBHSTSTS_BYTE_DONE, SMBHSTSTS);
+                               outb_p(SMBHSTSTS_INTR, SMBHSTSTS);
+                               return -EPROTO;
+                       }
                        data->block[0] = len;
                }
 
@@ -371,30 +367,19 @@ static int i801_block_transaction_byte_by_byte(union i2c_smbus_data *data,
                        data->block[i] = inb_p(SMBBLKDAT);
                if (read_write == I2C_SMBUS_WRITE && i+1 <= len)
                        outb_p(data->block[i+1], SMBBLKDAT);
-               if ((temp & 0x9e) != 0x00)
-                       outb_p(temp, SMBHSTSTS);  /* signals SMBBLKDAT ready */
-
-               if ((temp = (0x1e & inb_p(SMBHSTSTS))) != 0x00) {
-                       dev_dbg(&I801_dev->dev,
-                               "Bad status (%02x) at end of transaction\n",
-                               temp);
-               }
-               dev_dbg(&I801_dev->dev, "Block (post %d): CNT=%02x, CMD=%02x, "
-                       "ADD=%02x, DAT0=%02x, DAT1=%02x, BLKDAT=%02x\n", i,
-                       inb_p(SMBHSTCNT), inb_p(SMBHSTCMD), inb_p(SMBHSTADD),
-                       inb_p(SMBHSTDAT0), inb_p(SMBHSTDAT1), inb_p(SMBBLKDAT));
 
-               if (result < 0)
-                       return result;
+               /* signals SMBBLKDAT ready */
+               outb_p(SMBHSTSTS_BYTE_DONE | SMBHSTSTS_INTR, SMBHSTSTS);
        }
-       return result;
+
+       return 0;
 }
 
 static int i801_set_block_buffer_mode(void)
 {
        outb_p(inb_p(SMBAUXCTL) | SMBAUXCTL_E32B, SMBAUXCTL);
        if ((inb_p(SMBAUXCTL) & SMBAUXCTL_E32B) == 0)
-               return -1;
+               return -EIO;
        return 0;
 }
 
@@ -414,7 +399,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
                } else if (!(i801_features & FEATURE_I2C_BLOCK_READ)) {
                        dev_err(&I801_dev->dev,
                                "I2C block read is unsupported!\n");
-                       return -1;
+                       return -EOPNOTSUPP;
                }
        }
 
@@ -449,7 +434,7 @@ static int i801_block_transaction(union i2c_smbus_data *data, char read_write,
        return result;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 i801_access(struct i2c_adapter * adap, u16 addr,
                       unsigned short flags, char read_write, u8 command,
                       int size, union i2c_smbus_data * data)
@@ -511,10 +496,9 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
                        outb_p(command, SMBHSTCMD);
                block = 1;
                break;
-       case I2C_SMBUS_PROC_CALL:
        default:
                dev_err(&I801_dev->dev, "Unsupported transaction %d\n", size);
-               return -1;
+               return -EOPNOTSUPP;
        }
 
        if (hwpec)      /* enable/disable hardware PEC */
@@ -537,7 +521,7 @@ static s32 i801_access(struct i2c_adapter * adap, u16 addr,
        if(block)
                return ret;
        if(ret)
-               return -1;
+               return ret;
        if ((read_write == I2C_SMBUS_WRITE) || (xact == I801_QUICK))
                return 0;
 
@@ -572,7 +556,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter i801_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_I801,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
@@ -639,6 +623,10 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
                goto exit;
        }
 
+       err = acpi_check_resource_conflict(&dev->resource[SMBBAR]);
+       if (err)
+               goto exit;
+
        err = pci_request_region(dev, SMBBAR, i801_driver.name);
        if (err) {
                dev_err(&dev->dev, "Failed to request SMBus region "
diff --git a/drivers/i2c/busses/i2c-i810.c b/drivers/i2c/busses/i2c-i810.c
deleted file mode 100644 (file)
index 42e8d94..0000000
+++ /dev/null
@@ -1,260 +0,0 @@
-/*
-    i2c-i810.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
-    Copyright (c) 1998, 1999, 2000  Frodo Looijaard <frodol@dds.nl>,
-    Philip Edelbrock <phil@netroedge.com>,
-    Ralph Metzler <rjkm@thp.uni-koeln.de>, and
-    Mark D. Studebaker <mdsxyz123@yahoo.com>
-    
-    Based on code written by Ralph Metzler <rjkm@thp.uni-koeln.de> and
-    Simon 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.
-*/
-/*
-   This interfaces to the I810/I815 to provide access to
-   the DDC Bus and the I2C Bus.
-
-   SUPPORTED DEVICES   PCI ID
-   i810AA              7121           
-   i810AB              7123           
-   i810E               7125           
-   i815                        1132           
-   i845G               2562
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <asm/io.h>
-
-/* GPIO register locations */
-#define I810_IOCONTROL_OFFSET  0x5000
-#define I810_HVSYNC            0x00    /* not used */
-#define I810_GPIOA             0x10
-#define I810_GPIOB             0x14
-
-/* bit locations in the registers */
-#define SCL_DIR_MASK           0x0001
-#define SCL_DIR                        0x0002
-#define SCL_VAL_MASK           0x0004
-#define SCL_VAL_OUT            0x0008
-#define SCL_VAL_IN             0x0010
-#define SDA_DIR_MASK           0x0100
-#define SDA_DIR                        0x0200
-#define SDA_VAL_MASK           0x0400
-#define SDA_VAL_OUT            0x0800
-#define SDA_VAL_IN             0x1000
-
-/* initialization states */
-#define INIT1                  0x1
-#define INIT2                  0x2
-#define INIT3                  0x4
-
-/* delays */
-#define CYCLE_DELAY            10
-#define TIMEOUT                        (HZ / 2)
-
-static void __iomem *ioaddr;
-
-/* The i810 GPIO registers have individual masks for each bit
-   so we never have to read before writing. Nice. */
-
-static void bit_i810i2c_setscl(void *data, int val)
-{
-       writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
-            ioaddr + I810_GPIOB);
-       readl(ioaddr + I810_GPIOB);     /* flush posted write */
-}
-
-static void bit_i810i2c_setsda(void *data, int val)
-{
-       writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
-            ioaddr + I810_GPIOB);
-       readl(ioaddr + I810_GPIOB);     /* flush posted write */
-}
-
-/* The GPIO pins are open drain, so the pins could always remain outputs.
-   However, some chip versions don't latch the inputs unless they
-   are set as inputs.
-   We rely on the i2c-algo-bit routines to set the pins high before
-   reading the input from other chips. Following guidance in the 815
-   prog. ref. guide, we do a "dummy write" of 0 to the register before
-   reading which forces the input value to be latched. We presume this
-   applies to the 810 as well; shouldn't hurt anyway. This is necessary to get
-   i2c_algo_bit bit_test=1 to pass. */
-
-static int bit_i810i2c_getscl(void *data)
-{
-       writel(SCL_DIR_MASK, ioaddr + I810_GPIOB);
-       writel(0, ioaddr + I810_GPIOB);
-       return (0 != (readl(ioaddr + I810_GPIOB) & SCL_VAL_IN));
-}
-
-static int bit_i810i2c_getsda(void *data)
-{
-       writel(SDA_DIR_MASK, ioaddr + I810_GPIOB);
-       writel(0, ioaddr + I810_GPIOB);
-       return (0 != (readl(ioaddr + I810_GPIOB) & SDA_VAL_IN));
-}
-
-static void bit_i810ddc_setscl(void *data, int val)
-{
-       writel((val ? SCL_VAL_OUT : 0) | SCL_DIR | SCL_DIR_MASK | SCL_VAL_MASK,
-            ioaddr + I810_GPIOA);
-       readl(ioaddr + I810_GPIOA);     /* flush posted write */
-}
-
-static void bit_i810ddc_setsda(void *data, int val)
-{
-       writel((val ? SDA_VAL_OUT : 0) | SDA_DIR | SDA_DIR_MASK | SDA_VAL_MASK,
-            ioaddr + I810_GPIOA);
-       readl(ioaddr + I810_GPIOA);     /* flush posted write */
-}
-
-static int bit_i810ddc_getscl(void *data)
-{
-       writel(SCL_DIR_MASK, ioaddr + I810_GPIOA);
-       writel(0, ioaddr + I810_GPIOA);
-       return (0 != (readl(ioaddr + I810_GPIOA) & SCL_VAL_IN));
-}
-
-static int bit_i810ddc_getsda(void *data)
-{
-       writel(SDA_DIR_MASK, ioaddr + I810_GPIOA);
-       writel(0, ioaddr + I810_GPIOA);
-       return (0 != (readl(ioaddr + I810_GPIOA) & SDA_VAL_IN));
-}
-
-static int config_i810(struct pci_dev *dev)
-{
-       unsigned long cadr;
-
-       /* map I810 memory */
-       cadr = dev->resource[1].start;
-       cadr += I810_IOCONTROL_OFFSET;
-       cadr &= PCI_BASE_ADDRESS_MEM_MASK;
-       ioaddr = ioremap_nocache(cadr, 0x1000);
-       if (ioaddr) {
-               bit_i810i2c_setscl(NULL, 1);
-               bit_i810i2c_setsda(NULL, 1);
-               bit_i810ddc_setscl(NULL, 1);
-               bit_i810ddc_setsda(NULL, 1);
-               return 0;
-       }
-       return -ENODEV;
-}
-
-static struct i2c_algo_bit_data i810_i2c_bit_data = {
-       .setsda         = bit_i810i2c_setsda,
-       .setscl         = bit_i810i2c_setscl,
-       .getsda         = bit_i810i2c_getsda,
-       .getscl         = bit_i810i2c_getscl,
-       .udelay         = CYCLE_DELAY,
-       .timeout        = TIMEOUT,
-};
-
-static struct i2c_adapter i810_i2c_adapter = {
-       .owner          = THIS_MODULE,
-       .id             = I2C_HW_B_I810,
-       .name           = "I810/I815 I2C Adapter",
-       .algo_data      = &i810_i2c_bit_data,
-};
-
-static struct i2c_algo_bit_data i810_ddc_bit_data = {
-       .setsda         = bit_i810ddc_setsda,
-       .setscl         = bit_i810ddc_setscl,
-       .getsda         = bit_i810ddc_getsda,
-       .getscl         = bit_i810ddc_getscl,
-       .udelay         = CYCLE_DELAY,
-       .timeout        = TIMEOUT,
-};
-
-static struct i2c_adapter i810_ddc_adapter = {
-       .owner          = THIS_MODULE,
-       .id             = I2C_HW_B_I810,
-       .name           = "I810/I815 DDC Adapter",
-       .algo_data      = &i810_ddc_bit_data,
-};
-
-static struct pci_device_id i810_ids[] __devinitdata = {
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG1) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810_IG3) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82810E_IG) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82815_CGC) },
-       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82845G_IG) },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE (pci, i810_ids);
-
-static int __devinit i810_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       int retval;
-
-       retval = config_i810(dev);
-       if (retval)
-               return retval;
-       dev_info(&dev->dev, "i810/i815 i2c device found.\n");
-
-       /* set up the sysfs linkage to our parent device */
-       i810_i2c_adapter.dev.parent = &dev->dev;
-       i810_ddc_adapter.dev.parent = &dev->dev;
-
-       retval = i2c_bit_add_bus(&i810_i2c_adapter);
-       if (retval)
-               return retval;
-       retval = i2c_bit_add_bus(&i810_ddc_adapter);
-       if (retval)
-               i2c_del_adapter(&i810_i2c_adapter);
-       return retval;
-}
-
-static void __devexit i810_remove(struct pci_dev *dev)
-{
-       i2c_del_adapter(&i810_ddc_adapter);
-       i2c_del_adapter(&i810_i2c_adapter);
-       iounmap(ioaddr);
-}
-
-static struct pci_driver i810_driver = {
-       .name           = "i810_smbus",
-       .id_table       = i810_ids,
-       .probe          = i810_probe,
-       .remove         = __devexit_p(i810_remove),
-};
-
-static int __init i2c_i810_init(void)
-{
-       return pci_register_driver(&i810_driver);
-}
-
-static void __exit i2c_i810_exit(void)
-{
-       pci_unregister_driver(&i810_driver);
-}
-
-MODULE_AUTHOR("Frodo Looijaard <frodol@dds.nl>, "
-               "Philip Edelbrock <phil@netroedge.com>, "
-               "Ralph Metzler <rjkm@thp.uni-koeln.de>, "
-               "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
-MODULE_DESCRIPTION("I810/I815 I2C/DDC driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_i810_init);
-module_exit(i2c_i810_exit);
index 85dbf34382e1f54a3d964a2f71abf4f214457656..651f2f1ae5b7e96080e2664088695f608e059b4b 100644 (file)
 #include <asm/io.h>
 #include <linux/i2c.h>
 #include <linux/i2c-id.h>
-
-#ifdef CONFIG_IBM_OCP
-#include <asm/ocp.h>
-#include <asm/ibm4xx.h>
-#else
 #include <linux/of_platform.h>
-#endif
+#include <linux/of_i2c.h>
 
 #include "i2c-ibm_iic.h"
 
@@ -665,180 +660,6 @@ static inline u8 iic_clckdiv(unsigned int opb)
        return (u8)((opb + 9) / 10 - 1);
 }
 
-#ifdef CONFIG_IBM_OCP
-/*
- * Register single IIC interface
- */
-static int __devinit iic_probe(struct ocp_device *ocp){
-
-       struct ibm_iic_private* dev;
-       struct i2c_adapter* adap;
-       struct ocp_func_iic_data* iic_data = ocp->def->additions;
-       int ret;
-
-       if (!iic_data)
-               printk(KERN_WARNING"ibm-iic%d: missing additional data!\n",
-                       ocp->def->index);
-
-       if (!(dev = kzalloc(sizeof(*dev), GFP_KERNEL))) {
-               printk(KERN_ERR "ibm-iic%d: failed to allocate device data\n",
-                       ocp->def->index);
-               return -ENOMEM;
-       }
-
-       dev->idx = ocp->def->index;
-       ocp_set_drvdata(ocp, dev);
-
-       if (!request_mem_region(ocp->def->paddr, sizeof(struct iic_regs),
-                               "ibm_iic")) {
-               ret = -EBUSY;
-               goto fail1;
-       }
-
-       if (!(dev->vaddr = ioremap(ocp->def->paddr, sizeof(struct iic_regs)))){
-               printk(KERN_ERR "ibm-iic%d: failed to ioremap device registers\n",
-                       dev->idx);
-               ret = -ENXIO;
-               goto fail2;
-       }
-
-       init_waitqueue_head(&dev->wq);
-
-       dev->irq = iic_force_poll ? -1 : ocp->def->irq;
-       if (dev->irq >= 0){
-               /* Disable interrupts until we finish initialization,
-                  assumes level-sensitive IRQ setup...
-                */
-               iic_interrupt_mode(dev, 0);
-               if (request_irq(dev->irq, iic_handler, 0, "IBM IIC", dev)){
-                       printk(KERN_ERR "ibm-iic%d: request_irq %d failed\n",
-                               dev->idx, dev->irq);
-                       /* Fallback to the polling mode */
-                       dev->irq = -1;
-               }
-       }
-
-       if (dev->irq < 0)
-               printk(KERN_WARNING "ibm-iic%d: using polling mode\n",
-                       dev->idx);
-
-       /* Board specific settings */
-       dev->fast_mode = iic_force_fast ? 1 : (iic_data ? iic_data->fast_mode : 0);
-
-       /* clckdiv is the same for *all* IIC interfaces,
-        * but I'd rather make a copy than introduce another global. --ebs
-        */
-       dev->clckdiv = iic_clckdiv(ocp_sys_info.opb_bus_freq);
-       DBG("%d: clckdiv = %d\n", dev->idx, dev->clckdiv);
-
-       /* Initialize IIC interface */
-       iic_dev_init(dev);
-
-       /* Register it with i2c layer */
-       adap = &dev->adap;
-       adap->dev.parent = &ocp->dev;
-       strcpy(adap->name, "IBM IIC");
-       i2c_set_adapdata(adap, dev);
-       adap->id = I2C_HW_OCP;
-       adap->class = I2C_CLASS_HWMON;
-       adap->algo = &iic_algo;
-       adap->client_register = NULL;
-       adap->client_unregister = NULL;
-       adap->timeout = 1;
-
-       /*
-        * If "dev->idx" is negative we consider it as zero.
-        * The reason to do so is to avoid sysfs names that only make
-        * sense when there are multiple adapters.
-        */
-       adap->nr = dev->idx >= 0 ? dev->idx : 0;
-
-       if ((ret = i2c_add_numbered_adapter(adap)) < 0) {
-               printk(KERN_ERR "ibm-iic%d: failed to register i2c adapter\n",
-                       dev->idx);
-               goto fail;
-       }
-
-       printk(KERN_INFO "ibm-iic%d: using %s mode\n", dev->idx,
-               dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
-
-       return 0;
-
-fail:
-       if (dev->irq >= 0){
-               iic_interrupt_mode(dev, 0);
-               free_irq(dev->irq, dev);
-       }
-
-       iounmap(dev->vaddr);
-fail2:
-       release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
-fail1:
-       ocp_set_drvdata(ocp, NULL);
-       kfree(dev);
-       return ret;
-}
-
-/*
- * Cleanup initialized IIC interface
- */
-static void __devexit iic_remove(struct ocp_device *ocp)
-{
-       struct ibm_iic_private* dev = (struct ibm_iic_private*)ocp_get_drvdata(ocp);
-       BUG_ON(dev == NULL);
-       if (i2c_del_adapter(&dev->adap)){
-               printk(KERN_ERR "ibm-iic%d: failed to delete i2c adapter :(\n",
-                       dev->idx);
-               /* That's *very* bad, just shutdown IRQ ... */
-               if (dev->irq >= 0){
-                   iic_interrupt_mode(dev, 0);
-                   free_irq(dev->irq, dev);
-                   dev->irq = -1;
-               }
-       } else {
-               if (dev->irq >= 0){
-                   iic_interrupt_mode(dev, 0);
-                   free_irq(dev->irq, dev);
-               }
-               iounmap(dev->vaddr);
-               release_mem_region(ocp->def->paddr, sizeof(struct iic_regs));
-               kfree(dev);
-       }
-}
-
-static struct ocp_device_id ibm_iic_ids[] __devinitdata =
-{
-       { .vendor = OCP_VENDOR_IBM, .function = OCP_FUNC_IIC },
-       { .vendor = OCP_VENDOR_INVALID }
-};
-
-MODULE_DEVICE_TABLE(ocp, ibm_iic_ids);
-
-static struct ocp_driver ibm_iic_driver =
-{
-       .name           = "iic",
-       .id_table       = ibm_iic_ids,
-       .probe          = iic_probe,
-       .remove         = __devexit_p(iic_remove),
-#if defined(CONFIG_PM)
-       .suspend        = NULL,
-       .resume         = NULL,
-#endif
-};
-
-static int __init iic_init(void)
-{
-       printk(KERN_INFO "IBM IIC driver v" DRIVER_VERSION "\n");
-       return ocp_register_driver(&ibm_iic_driver);
-}
-
-static void __exit iic_exit(void)
-{
-       ocp_unregister_driver(&ibm_iic_driver);
-}
-
-#else  /* !CONFIG_IBM_OCP */
-
 static int __devinit iic_request_irq(struct of_device *ofdev,
                                     struct ibm_iic_private *dev)
 {
@@ -876,7 +697,7 @@ static int __devinit iic_probe(struct of_device *ofdev,
        struct device_node *np = ofdev->node;
        struct ibm_iic_private *dev;
        struct i2c_adapter *adap;
-       const u32 *indexp, *freq;
+       const u32 *freq;
        int ret;
 
        dev = kzalloc(sizeof(*dev), GFP_KERNEL);
@@ -887,14 +708,6 @@ static int __devinit iic_probe(struct of_device *ofdev,
 
        dev_set_drvdata(&ofdev->dev, dev);
 
-       indexp = of_get_property(np, "index", NULL);
-       if (!indexp) {
-               dev_err(&ofdev->dev, "no index specified\n");
-               ret = -EINVAL;
-               goto error_cleanup;
-       }
-       dev->idx = *indexp;
-
        dev->vaddr = of_iomap(np, 0);
        if (dev->vaddr == NULL) {
                dev_err(&ofdev->dev, "failed to iomap device\n");
@@ -934,17 +747,19 @@ static int __devinit iic_probe(struct of_device *ofdev,
        strlcpy(adap->name, "IBM IIC", sizeof(adap->name));
        i2c_set_adapdata(adap, dev);
        adap->id = I2C_HW_OCP;
-       adap->class = I2C_CLASS_HWMON;
+       adap->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adap->algo = &iic_algo;
        adap->timeout = 1;
-       adap->nr = dev->idx;
 
-       ret = i2c_add_numbered_adapter(adap);
+       ret = i2c_add_adapter(adap);
        if (ret  < 0) {
                dev_err(&ofdev->dev, "failed to register i2c adapter\n");
                goto error_cleanup;
        }
 
+       /* Now register all the child nodes */
+       of_register_i2c_devices(adap, np);
+
        dev_info(&ofdev->dev, "using %s mode\n",
                 dev->fast_mode ? "fast (400 kHz)" : "standard (100 kHz)");
 
@@ -987,11 +802,7 @@ static int __devexit iic_remove(struct of_device *ofdev)
 }
 
 static const struct of_device_id ibm_iic_match[] = {
-       { .compatible = "ibm,iic-405ex", },
-       { .compatible = "ibm,iic-405gp", },
-       { .compatible = "ibm,iic-440gp", },
-       { .compatible = "ibm,iic-440gpx", },
-       { .compatible = "ibm,iic-440grx", },
+       { .compatible = "ibm,iic", },
        {}
 };
 
@@ -1011,7 +822,6 @@ static void __exit iic_exit(void)
 {
        of_unregister_platform_driver(&ibm_iic_driver);
 }
-#endif /* CONFIG_IBM_OCP */
 
 module_init(iic_init);
 module_exit(iic_exit);
index 39884e7975945e8954ed4bb8f1e8194fab5fd895..fc2714ac0c0f4ba865584f5012fce1dc563f3d06 100644 (file)
@@ -482,7 +482,7 @@ iop3xx_i2c_probe(struct platform_device *pdev)
        memcpy(new_adapter->name, pdev->name, strlen(pdev->name));
        new_adapter->id = I2C_HW_IOP3XX;
        new_adapter->owner = THIS_MODULE;
-       new_adapter->class = I2C_CLASS_HWMON;
+       new_adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        new_adapter->dev.parent = &pdev->dev;
        new_adapter->nr = pdev->id;
 
diff --git a/drivers/i2c/busses/i2c-isch.c b/drivers/i2c/busses/i2c-isch.c
new file mode 100644 (file)
index 0000000..b9c01aa
--- /dev/null
@@ -0,0 +1,339 @@
+/*
+    i2c-isch.c - Linux kernel driver for Intel SCH chipset SMBus
+    - Based on i2c-piix4.c
+    Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
+    Philip Edelbrock <phil@netroedge.com>
+    - Intel SCH support
+    Copyright (c) 2007 - 2008 Jacob Jun Pan <jacob.jun.pan@intel.com>
+
+    This program is free software; you can redistribute it and/or modify
+    it under the terms of the GNU General Public License version 2 as
+    published by the Free Software Foundation.
+
+    This program is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with this program; if not, write to the Free Software
+    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+*/
+
+/*
+   Supports:
+       Intel SCH chipsets (AF82US15W, AF82US15L, AF82UL11L)
+   Note: we assume there can only be one device, with one SMBus interface.
+*/
+
+#include <linux/module.h>
+#include <linux/pci.h>
+#include <linux/kernel.h>
+#include <linux/delay.h>
+#include <linux/stddef.h>
+#include <linux/ioport.h>
+#include <linux/i2c.h>
+#include <linux/init.h>
+#include <linux/io.h>
+#include <linux/acpi.h>
+
+/* SCH SMBus address offsets */
+#define SMBHSTCNT      (0 + sch_smba)
+#define SMBHSTSTS      (1 + sch_smba)
+#define SMBHSTADD      (4 + sch_smba) /* TSA */
+#define SMBHSTCMD      (5 + sch_smba)
+#define SMBHSTDAT0     (6 + sch_smba)
+#define SMBHSTDAT1     (7 + sch_smba)
+#define SMBBLKDAT      (0x20 + sch_smba)
+
+/* count for request_region */
+#define SMBIOSIZE      64
+
+/* PCI Address Constants */
+#define SMBBA_SCH      0x40
+
+/* Other settings */
+#define MAX_TIMEOUT    500
+
+/* I2C constants */
+#define SCH_QUICK              0x00
+#define SCH_BYTE               0x01
+#define SCH_BYTE_DATA          0x02
+#define SCH_WORD_DATA          0x03
+#define SCH_BLOCK_DATA         0x05
+
+static unsigned short sch_smba;
+static struct pci_driver sch_driver;
+static struct i2c_adapter sch_adapter;
+
+/*
+ * Start the i2c transaction -- the i2c_access will prepare the transaction
+ * and this function will execute it.
+ * return 0 for success and others for failure.
+ */
+static int sch_transaction(void)
+{
+       int temp;
+       int result = 0;
+       int timeout = 0;
+
+       dev_dbg(&sch_adapter.dev, "Transaction (pre): CNT=%02x, CMD=%02x, "
+               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
+               inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
+               inb(SMBHSTDAT1));
+
+       /* Make sure the SMBus host is ready to start transmitting */
+       temp = inb(SMBHSTSTS) & 0x0f;
+       if (temp) {
+               /* Can not be busy since we checked it in sch_access */
+               if (temp & 0x01) {
+                       dev_dbg(&sch_adapter.dev, "Completion (%02x). "
+                               "Clear...\n", temp);
+               }
+               if (temp & 0x06) {
+                       dev_dbg(&sch_adapter.dev, "SMBus error (%02x). "
+                               "Resetting...\n", temp);
+               }
+               outb(temp, SMBHSTSTS);
+               temp = inb(SMBHSTSTS) & 0x0f;
+               if (temp) {
+                       dev_err(&sch_adapter.dev,
+                               "SMBus is not ready: (%02x)\n", temp);
+                       return -EAGAIN;
+               }
+       }
+
+       /* start the transaction by setting bit 4 */
+       outb(inb(SMBHSTCNT) | 0x10, SMBHSTCNT);
+
+       do {
+               msleep(1);
+               temp = inb(SMBHSTSTS) & 0x0f;
+       } while ((temp & 0x08) && (timeout++ < MAX_TIMEOUT));
+
+       /* If the SMBus is still busy, we give up */
+       if (timeout >= MAX_TIMEOUT) {
+               dev_err(&sch_adapter.dev, "SMBus Timeout!\n");
+               result = -ETIMEDOUT;
+       }
+       if (temp & 0x04) {
+               result = -EIO;
+               dev_dbg(&sch_adapter.dev, "Bus collision! SMBus may be "
+                       "locked until next hard reset. (sorry!)\n");
+               /* Clock stops and slave is stuck in mid-transmission */
+       } else if (temp & 0x02) {
+               result = -EIO;
+               dev_err(&sch_adapter.dev, "Error: no response!\n");
+       } else if (temp & 0x01) {
+               dev_dbg(&sch_adapter.dev, "Post complete!\n");
+               outb(temp, SMBHSTSTS);
+               temp = inb(SMBHSTSTS) & 0x07;
+               if (temp & 0x06) {
+                       /* Completion clear failed */
+                       dev_dbg(&sch_adapter.dev, "Failed reset at end of "
+                               "transaction (%02x), Bus error!\n", temp);
+               }
+       } else {
+               result = -ENXIO;
+               dev_dbg(&sch_adapter.dev, "No such address.\n");
+       }
+       dev_dbg(&sch_adapter.dev, "Transaction (post): CNT=%02x, CMD=%02x, "
+               "ADD=%02x, DAT0=%02x, DAT1=%02x\n", inb(SMBHSTCNT),
+               inb(SMBHSTCMD), inb(SMBHSTADD), inb(SMBHSTDAT0),
+               inb(SMBHSTDAT1));
+       return result;
+}
+
+/*
+ * This is the main access entry for i2c-sch access
+ * adap is i2c_adapter pointer, addr is the i2c device bus address, read_write
+ * (0 for read and 1 for write), size is i2c transaction type and data is the
+ * union of transaction for data to be transfered or data read from bus.
+ * return 0 for success and others for failure.
+ */
+static s32 sch_access(struct i2c_adapter *adap, u16 addr,
+                unsigned short flags, char read_write,
+                u8 command, int size, union i2c_smbus_data *data)
+{
+       int i, len, temp, rc;
+
+       /* Make sure the SMBus host is not busy */
+       temp = inb(SMBHSTSTS) & 0x0f;
+       if (temp & 0x08) {
+               dev_dbg(&sch_adapter.dev, "SMBus busy (%02x)\n", temp);
+               return -EAGAIN;
+       }
+       dev_dbg(&sch_adapter.dev, "access size: %d %s\n", size,
+               (read_write)?"READ":"WRITE");
+       switch (size) {
+       case I2C_SMBUS_QUICK:
+               outb((addr << 1) | read_write, SMBHSTADD);
+               size = SCH_QUICK;
+               break;
+       case I2C_SMBUS_BYTE:
+               outb((addr << 1) | read_write, SMBHSTADD);
+               if (read_write == I2C_SMBUS_WRITE)
+                       outb(command, SMBHSTCMD);
+               size = SCH_BYTE;
+               break;
+       case I2C_SMBUS_BYTE_DATA:
+               outb((addr << 1) | read_write, SMBHSTADD);
+               outb(command, SMBHSTCMD);
+               if (read_write == I2C_SMBUS_WRITE)
+                       outb(data->byte, SMBHSTDAT0);
+               size = SCH_BYTE_DATA;
+               break;
+       case I2C_SMBUS_WORD_DATA:
+               outb((addr << 1) | read_write, SMBHSTADD);
+               outb(command, SMBHSTCMD);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       outb(data->word & 0xff, SMBHSTDAT0);
+                       outb((data->word & 0xff00) >> 8, SMBHSTDAT1);
+               }
+               size = SCH_WORD_DATA;
+               break;
+       case I2C_SMBUS_BLOCK_DATA:
+               outb((addr << 1) | read_write, SMBHSTADD);
+               outb(command, SMBHSTCMD);
+               if (read_write == I2C_SMBUS_WRITE) {
+                       len = data->block[0];
+                       if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
+                               return -EINVAL;
+                       outb(len, SMBHSTDAT0);
+                       for (i = 1; i <= len; i++)
+                               outb(data->block[i], SMBBLKDAT+i-1);
+               }
+               size = SCH_BLOCK_DATA;
+               break;
+       default:
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
+       }
+       dev_dbg(&sch_adapter.dev, "write size %d to 0x%04x\n", size, SMBHSTCNT);
+       outb((inb(SMBHSTCNT) & 0xb0) | (size & 0x7), SMBHSTCNT);
+
+       rc = sch_transaction();
+       if (rc) /* Error in transaction */
+               return rc;
+
+       if ((read_write == I2C_SMBUS_WRITE) || (size == SCH_QUICK))
+               return 0;
+
+       switch (size) {
+       case SCH_BYTE:
+       case SCH_BYTE_DATA:
+               data->byte = inb(SMBHSTDAT0);
+               break;
+       case SCH_WORD_DATA:
+               data->word = inb(SMBHSTDAT0) + (inb(SMBHSTDAT1) << 8);
+               break;
+       case SCH_BLOCK_DATA:
+               data->block[0] = inb(SMBHSTDAT0);
+               if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
+                       return -EPROTO;
+               for (i = 1; i <= data->block[0]; i++)
+                       data->block[i] = inb(SMBBLKDAT+i-1);
+               break;
+       }
+       return 0;
+}
+
+static u32 sch_func(struct i2c_adapter *adapter)
+{
+       return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+           I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+           I2C_FUNC_SMBUS_BLOCK_DATA;
+}
+
+static const struct i2c_algorithm smbus_algorithm = {
+       .smbus_xfer     = sch_access,
+       .functionality  = sch_func,
+};
+
+static struct i2c_adapter sch_adapter = {
+       .owner          = THIS_MODULE,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
+       .algo           = &smbus_algorithm,
+};
+
+static struct pci_device_id sch_ids[] = {
+       { PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_SCH_LPC) },
+       { 0, }
+};
+
+MODULE_DEVICE_TABLE(pci, sch_ids);
+
+static int __devinit sch_probe(struct pci_dev *dev,
+                               const struct pci_device_id *id)
+{
+       int retval;
+       unsigned int smba;
+
+       pci_read_config_dword(dev, SMBBA_SCH, &smba);
+       if (!(smba & (1 << 31))) {
+               dev_err(&dev->dev, "SMBus I/O space disabled!\n");
+               return -ENODEV;
+       }
+
+       sch_smba = (unsigned short)smba;
+       if (sch_smba == 0) {
+               dev_err(&dev->dev, "SMBus base address uninitialized!\n");
+               return -ENODEV;
+       }
+       if (acpi_check_region(sch_smba, SMBIOSIZE, sch_driver.name))
+               return -EBUSY;
+       if (!request_region(sch_smba, SMBIOSIZE, sch_driver.name)) {
+               dev_err(&dev->dev, "SMBus region 0x%x already in use!\n",
+                       sch_smba);
+               return -EBUSY;
+       }
+       dev_dbg(&dev->dev, "SMBA = 0x%X\n", sch_smba);
+
+       /* set up the sysfs linkage to our parent device */
+       sch_adapter.dev.parent = &dev->dev;
+
+       snprintf(sch_adapter.name, sizeof(sch_adapter.name),
+               "SMBus SCH adapter at %04x", sch_smba);
+
+       retval = i2c_add_adapter(&sch_adapter);
+       if (retval) {
+               dev_err(&dev->dev, "Couldn't register adapter!\n");
+               release_region(sch_smba, SMBIOSIZE);
+               sch_smba = 0;
+       }
+
+       return retval;
+}
+
+static void __devexit sch_remove(struct pci_dev *dev)
+{
+       if (sch_smba) {
+               i2c_del_adapter(&sch_adapter);
+               release_region(sch_smba, SMBIOSIZE);
+               sch_smba = 0;
+       }
+}
+
+static struct pci_driver sch_driver = {
+       .name           = "isch_smbus",
+       .id_table       = sch_ids,
+       .probe          = sch_probe,
+       .remove         = __devexit_p(sch_remove),
+};
+
+static int __init i2c_sch_init(void)
+{
+       return pci_register_driver(&sch_driver);
+}
+
+static void __exit i2c_sch_exit(void)
+{
+       pci_unregister_driver(&sch_driver);
+}
+
+MODULE_AUTHOR("Jacob Pan <jacob.jun.pan@intel.com>");
+MODULE_DESCRIPTION("Intel SCH SMBus driver");
+MODULE_LICENSE("GPL");
+
+module_init(i2c_sch_init);
+module_exit(i2c_sch_exit);
index a076129de7e811acb2434864ef2d48fccbeafa3b..10b9342a36c21241bb3c0ca36960801148053239 100644 (file)
@@ -311,7 +311,7 @@ static struct i2c_adapter mpc_ops = {
        .name = "MPC adapter",
        .id = I2C_HW_MPC107,
        .algo = &mpc_algo,
-       .class = I2C_CLASS_HWMON,
+       .class = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .timeout = 1,
 };
 
index 036e6a883e6788e1564a56ae04afb227971681d6..9e8118d2fe64cccfa54e745337982569e0710064 100644 (file)
@@ -530,7 +530,7 @@ mv64xxx_i2c_probe(struct platform_device *pd)
        drv_data->adapter.id = I2C_HW_MV64XXX;
        drv_data->adapter.algo = &mv64xxx_i2c_algo;
        drv_data->adapter.owner = THIS_MODULE;
-       drv_data->adapter.class = I2C_CLASS_HWMON;
+       drv_data->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        drv_data->adapter.timeout = pdata->timeout;
        drv_data->adapter.nr = pd->id;
        platform_set_drvdata(pd, drv_data);
diff --git a/drivers/i2c/busses/i2c-nforce2-s4985.c b/drivers/i2c/busses/i2c-nforce2-s4985.c
new file mode 100644 (file)
index 0000000..6a8995d
--- /dev/null
@@ -0,0 +1,257 @@
+/*
+ * i2c-nforce2-s4985.c - i2c-nforce2 extras for the Tyan S4985 motherboard
+ *
+ * Copyright (C) 2008 Jean Delvare <khali@linux-fr.org>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
+ */
+
+/*
+ * We select the channels by sending commands to the Philips
+ * PCA9556 chip at I2C address 0x18. The main adapter is used for
+ * the non-multiplexed part of the bus, and 4 virtual adapters
+ * are defined for the multiplexed addresses: 0x50-0x53 (memory
+ * module EEPROM) located on channels 1-4. We define one virtual
+ * adapter per CPU, which corresponds to one multiplexed channel:
+ *   CPU0: virtual adapter 1, channel 1
+ *   CPU1: virtual adapter 2, channel 2
+ *   CPU2: virtual adapter 3, channel 3
+ *   CPU3: virtual adapter 4, channel 4
+ */
+
+#include <linux/module.h>
+#include <linux/kernel.h>
+#include <linux/slab.h>
+#include <linux/init.h>
+#include <linux/i2c.h>
+#include <linux/mutex.h>
+
+extern struct i2c_adapter *nforce2_smbus;
+
+static struct i2c_adapter *s4985_adapter;
+static struct i2c_algorithm *s4985_algo;
+
+/* Wrapper access functions for multiplexed SMBus */
+static DEFINE_MUTEX(nforce2_lock);
+
+static s32 nforce2_access_virt0(struct i2c_adapter *adap, u16 addr,
+                               unsigned short flags, char read_write,
+                               u8 command, int size,
+                               union i2c_smbus_data *data)
+{
+       int error;
+
+       /* We exclude the multiplexed addresses */
+       if ((addr & 0xfc) == 0x50 || (addr & 0xfc) == 0x30
+        || addr == 0x18)
+               return -ENXIO;
+
+       mutex_lock(&nforce2_lock);
+       error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
+                                               command, size, data);
+       mutex_unlock(&nforce2_lock);
+
+       return error;
+}
+
+/* We remember the last used channels combination so as to only switch
+   channels when it is really needed. This greatly reduces the SMBus
+   overhead, but also assumes that nobody will be writing to the PCA9556
+   in our back. */
+static u8 last_channels;
+
+static inline s32 nforce2_access_channel(struct i2c_adapter *adap, u16 addr,
+                                        unsigned short flags, char read_write,
+                                        u8 command, int size,
+                                        union i2c_smbus_data *data,
+                                        u8 channels)
+{
+       int error;
+
+       /* We exclude the non-multiplexed addresses */
+       if ((addr & 0xfc) != 0x50 && (addr & 0xfc) != 0x30)
+               return -ENXIO;
+
+       mutex_lock(&nforce2_lock);
+       if (last_channels != channels) {
+               union i2c_smbus_data mplxdata;
+               mplxdata.byte = channels;
+
+               error = nforce2_smbus->algo->smbus_xfer(adap, 0x18, 0,
+                                                       I2C_SMBUS_WRITE, 0x01,
+                                                       I2C_SMBUS_BYTE_DATA,
+                                                       &mplxdata);
+               if (error)
+                       goto UNLOCK;
+               last_channels = channels;
+       }
+       error = nforce2_smbus->algo->smbus_xfer(adap, addr, flags, read_write,
+                                               command, size, data);
+
+UNLOCK:
+       mutex_unlock(&nforce2_lock);
+       return error;
+}
+
+static s32 nforce2_access_virt1(struct i2c_adapter *adap, u16 addr,
+                               unsigned short flags, char read_write,
+                               u8 command, int size,
+                               union i2c_smbus_data *data)
+{
+       /* CPU0: channel 1 enabled */
+       return nforce2_access_channel(adap, addr, flags, read_write, command,
+                                     size, data, 0x02);
+}
+
+static s32 nforce2_access_virt2(struct i2c_adapter *adap, u16 addr,
+                               unsigned short flags, char read_write,
+                               u8 command, int size,
+                               union i2c_smbus_data *data)
+{
+       /* CPU1: channel 2 enabled */
+       return nforce2_access_channel(adap, addr, flags, read_write, command,
+                                     size, data, 0x04);
+}
+
+static s32 nforce2_access_virt3(struct i2c_adapter *adap, u16 addr,
+                               unsigned short flags, char read_write,
+                               u8 command, int size,
+                               union i2c_smbus_data *data)
+{
+       /* CPU2: channel 3 enabled */
+       return nforce2_access_channel(adap, addr, flags, read_write, command,
+                                     size, data, 0x08);
+}
+
+static s32 nforce2_access_virt4(struct i2c_adapter *adap, u16 addr,
+                               unsigned short flags, char read_write,
+                               u8 command, int size,
+                               union i2c_smbus_data *data)
+{
+       /* CPU3: channel 4 enabled */
+       return nforce2_access_channel(adap, addr, flags, read_write, command,
+                                     size, data, 0x10);
+}
+
+static int __init nforce2_s4985_init(void)
+{
+       int i, error;
+       union i2c_smbus_data ioconfig;
+
+       /* Unregister physical bus */
+       if (!nforce2_smbus)
+               return -ENODEV;
+       error = i2c_del_adapter(nforce2_smbus);
+       if (error) {
+               dev_err(&nforce2_smbus->dev, "Physical bus removal failed\n");
+               goto ERROR0;
+       }
+
+       printk(KERN_INFO "Enabling SMBus multiplexing for Tyan S4985\n");
+       /* Define the 5 virtual adapters and algorithms structures */
+       s4985_adapter = kzalloc(5 * sizeof(struct i2c_adapter), GFP_KERNEL);
+       if (!s4985_adapter) {
+               error = -ENOMEM;
+               goto ERROR1;
+       }
+       s4985_algo = kzalloc(5 * sizeof(struct i2c_algorithm), GFP_KERNEL);
+       if (!s4985_algo) {
+               error = -ENOMEM;
+               goto ERROR2;
+       }
+
+       /* Fill in the new structures */
+       s4985_algo[0] = *(nforce2_smbus->algo);
+       s4985_algo[0].smbus_xfer = nforce2_access_virt0;
+       s4985_adapter[0] = *nforce2_smbus;
+       s4985_adapter[0].algo = s4985_algo;
+       s4985_adapter[0].dev.parent = nforce2_smbus->dev.parent;
+       for (i = 1; i < 5; i++) {
+               s4985_algo[i] = *(nforce2_smbus->algo);
+               s4985_adapter[i] = *nforce2_smbus;
+               snprintf(s4985_adapter[i].name, sizeof(s4985_adapter[i].name),
+                        "SMBus nForce2 adapter (CPU%d)", i - 1);
+               s4985_adapter[i].algo = s4985_algo + i;
+               s4985_adapter[i].dev.parent = nforce2_smbus->dev.parent;
+       }
+       s4985_algo[1].smbus_xfer = nforce2_access_virt1;
+       s4985_algo[2].smbus_xfer = nforce2_access_virt2;
+       s4985_algo[3].smbus_xfer = nforce2_access_virt3;
+       s4985_algo[4].smbus_xfer = nforce2_access_virt4;
+
+       /* Configure the PCA9556 multiplexer */
+       ioconfig.byte = 0x00; /* All I/O to output mode */
+       error = nforce2_smbus->algo->smbus_xfer(nforce2_smbus, 0x18, 0,
+                                               I2C_SMBUS_WRITE, 0x03,
+                                               I2C_SMBUS_BYTE_DATA, &ioconfig);
+       if (error) {
+               dev_err(&nforce2_smbus->dev, "PCA9556 configuration failed\n");
+               error = -EIO;
+               goto ERROR3;
+       }
+
+       /* Register virtual adapters */
+       for (i = 0; i < 5; i++) {
+               error = i2c_add_adapter(s4985_adapter + i);
+               if (error) {
+                       dev_err(&nforce2_smbus->dev,
+                               "Virtual adapter %d registration "
+                               "failed, module not inserted\n", i);
+                       for (i--; i >= 0; i--)
+                               i2c_del_adapter(s4985_adapter + i);
+                       goto ERROR3;
+               }
+       }
+
+       return 0;
+
+ERROR3:
+       kfree(s4985_algo);
+       s4985_algo = NULL;
+ERROR2:
+       kfree(s4985_adapter);
+       s4985_adapter = NULL;
+ERROR1:
+       /* Restore physical bus */
+       i2c_add_adapter(nforce2_smbus);
+ERROR0:
+       return error;
+}
+
+static void __exit nforce2_s4985_exit(void)
+{
+       if (s4985_adapter) {
+               int i;
+
+               for (i = 0; i < 5; i++)
+                       i2c_del_adapter(s4985_adapter+i);
+               kfree(s4985_adapter);
+               s4985_adapter = NULL;
+       }
+       kfree(s4985_algo);
+       s4985_algo = NULL;
+
+       /* Restore physical bus */
+       if (i2c_add_adapter(nforce2_smbus))
+               dev_err(&nforce2_smbus->dev, "Physical bus restoration "
+                       "failed\n");
+}
+
+MODULE_AUTHOR("Jean Delvare <khali@linux-fr.org>");
+MODULE_DESCRIPTION("S4985 SMBus multiplexing");
+MODULE_LICENSE("GPL");
+
+module_init(nforce2_s4985_init);
+module_exit(nforce2_s4985_exit);
index 43c9f8df950913a85137e13b124a90df30ae2041..3b19bc41a60b4d66f5995ff8082939160341a412 100644 (file)
@@ -51,6 +51,7 @@
 #include <linux/i2c.h>
 #include <linux/delay.h>
 #include <linux/dmi.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 MODULE_LICENSE("GPL");
@@ -124,6 +125,20 @@ static struct dmi_system_id __devinitdata nforce2_dmi_blacklist2[] = {
 
 static struct pci_driver nforce2_driver;
 
+/* For multiplexing support, we need a global reference to the 1st
+   SMBus channel */
+#if defined CONFIG_I2C_NFORCE2_S4985 || defined CONFIG_I2C_NFORCE2_S4985_MODULE
+struct i2c_adapter *nforce2_smbus;
+EXPORT_SYMBOL_GPL(nforce2_smbus);
+
+static void nforce2_set_reference(struct i2c_adapter *adap)
+{
+       nforce2_smbus = adap;
+}
+#else
+static inline void nforce2_set_reference(struct i2c_adapter *adap) { }
+#endif
+
 static void nforce2_abort(struct i2c_adapter *adap)
 {
        struct nforce2_smbus *smbus = adap->algo_data;
@@ -158,16 +173,16 @@ static int nforce2_check_status(struct i2c_adapter *adap)
                dev_dbg(&adap->dev, "SMBus Timeout!\n");
                if (smbus->can_abort)
                        nforce2_abort(adap);
-               return -1;
+               return -ETIMEDOUT;
        }
        if (!(temp & NVIDIA_SMB_STS_DONE) || (temp & NVIDIA_SMB_STS_STATUS)) {
                dev_dbg(&adap->dev, "Transaction failed (0x%02x)!\n", temp);
-               return -1;
+               return -EIO;
        }
        return 0;
 }
 
-/* Return -1 on error */
+/* Return negative errno on error */
 static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
                unsigned short flags, char read_write,
                u8 command, int size, union i2c_smbus_data * data)
@@ -175,7 +190,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
        struct nforce2_smbus *smbus = adap->algo_data;
        unsigned char protocol, pec;
        u8 len;
-       int i;
+       int i, status;
 
        protocol = (read_write == I2C_SMBUS_READ) ? NVIDIA_SMB_PRTCL_READ :
                NVIDIA_SMB_PRTCL_WRITE;
@@ -219,7 +234,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
                                                "Transaction failed "
                                                "(requested block size: %d)\n",
                                                len);
-                                       return -1;
+                                       return -EINVAL;
                                }
                                outb_p(len, NVIDIA_SMB_BCNT);
                                for (i = 0; i < I2C_SMBUS_BLOCK_MAX; i++)
@@ -231,14 +246,15 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
 
                default:
                        dev_err(&adap->dev, "Unsupported transaction %d\n", size);
-                       return -1;
+                       return -EOPNOTSUPP;
        }
 
        outb_p((addr & 0x7f) << 1, NVIDIA_SMB_ADDR);
        outb_p(protocol, NVIDIA_SMB_PRTCL);
 
-       if (nforce2_check_status(adap))
-               return -1;
+       status = nforce2_check_status(adap);
+       if (status)
+               return status;
 
        if (read_write == I2C_SMBUS_WRITE)
                return 0;
@@ -260,7 +276,7 @@ static s32 nforce2_access(struct i2c_adapter * adap, u16 addr,
                                dev_err(&adap->dev, "Transaction failed "
                                        "(received block size: 0x%02x)\n",
                                        len);
-                               return -1;
+                               return -EPROTO;
                        }
                        for (i = 0; i < len; i++)
                                data->block[i+1] = inb_p(NVIDIA_SMB_DATA + i);
@@ -321,21 +337,26 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
                    != PCIBIOS_SUCCESSFUL) {
                        dev_err(&dev->dev, "Error reading PCI config for %s\n",
                                name);
-                       return -1;
+                       return -EIO;
                }
 
                smbus->base = iobase & PCI_BASE_ADDRESS_IO_MASK;
                smbus->size = 64;
        }
 
+       error = acpi_check_region(smbus->base, smbus->size,
+                                 nforce2_driver.name);
+       if (error)
+               return -1;
+
        if (!request_region(smbus->base, smbus->size, nforce2_driver.name)) {
                dev_err(&smbus->adapter.dev, "Error requesting region %02x .. %02X for %s\n",
                        smbus->base, smbus->base+smbus->size-1, name);
-               return -1;
+               return -EBUSY;
        }
        smbus->adapter.owner = THIS_MODULE;
        smbus->adapter.id = I2C_HW_SMBUS_NFORCE2;
-       smbus->adapter.class = I2C_CLASS_HWMON;
+       smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        smbus->adapter.algo = &smbus_algorithm;
        smbus->adapter.algo_data = smbus;
        smbus->adapter.dev.parent = &dev->dev;
@@ -346,7 +367,7 @@ static int __devinit nforce2_probe_smb (struct pci_dev *dev, int bar,
        if (error) {
                dev_err(&smbus->adapter.dev, "Failed to register adapter.\n");
                release_region(smbus->base, smbus->size);
-               return -1;
+               return error;
        }
        dev_info(&smbus->adapter.dev, "nForce2 SMBus adapter at %#x\n", smbus->base);
        return 0;
@@ -398,6 +419,7 @@ static int __devinit nforce2_probe(struct pci_dev *dev, const struct pci_device_
                return -ENODEV;
        }
 
+       nforce2_set_reference(&smbuses[0].adapter);
        return 0;
 }
 
@@ -406,6 +428,7 @@ static void __devexit nforce2_remove(struct pci_dev *dev)
 {
        struct nforce2_smbus *smbuses = (void*) pci_get_drvdata(dev);
 
+       nforce2_set_reference(NULL);
        if (smbuses[0].base) {
                i2c_del_adapter(&smbuses[0].adapter);
                release_region(smbuses[0].base, smbuses[0].size);
index f145692cbb76ad649901ccc3553443804bde3941..e5193bf754837bda5108651679c477ecd4248456 100644 (file)
@@ -29,6 +29,7 @@ struct ocores_i2c {
        int pos;
        int nmsgs;
        int state; /* see STATE_ */
+       int clock_khz;
 };
 
 /* registers */
@@ -173,8 +174,7 @@ static int ocores_xfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
                return -ETIMEDOUT;
 }
 
-static void ocores_init(struct ocores_i2c *i2c,
-                       struct ocores_i2c_platform_data *pdata)
+static void ocores_init(struct ocores_i2c *i2c)
 {
        int prescale;
        u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
@@ -182,7 +182,7 @@ static void ocores_init(struct ocores_i2c *i2c,
        /* make sure the device is disabled */
        oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
 
-       prescale = (pdata->clock_khz / (5*100)) - 1;
+       prescale = (i2c->clock_khz / (5*100)) - 1;
        oc_setreg(i2c, OCI2C_PRELOW, prescale & 0xff);
        oc_setreg(i2c, OCI2C_PREHIGH, prescale >> 8);
 
@@ -205,7 +205,7 @@ static const struct i2c_algorithm ocores_algorithm = {
 static struct i2c_adapter ocores_adapter = {
        .owner          = THIS_MODULE,
        .name           = "i2c-ocores",
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &ocores_algorithm,
 };
 
@@ -248,7 +248,8 @@ static int __devinit ocores_i2c_probe(struct platform_device *pdev)
        }
 
        i2c->regstep = pdata->regstep;
-       ocores_init(i2c, pdata);
+       i2c->clock_khz = pdata->clock_khz;
+       ocores_init(i2c);
 
        init_waitqueue_head(&i2c->wait);
        ret = request_irq(res2->start, ocores_isr, 0, pdev->name, i2c);
@@ -312,13 +313,40 @@ static int __devexit ocores_i2c_remove(struct platform_device* pdev)
        return 0;
 }
 
+#ifdef CONFIG_PM
+static int ocores_i2c_suspend(struct platform_device *pdev, pm_message_t state)
+{
+       struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+       u8 ctrl = oc_getreg(i2c, OCI2C_CONTROL);
+
+       /* make sure the device is disabled */
+       oc_setreg(i2c, OCI2C_CONTROL, ctrl & ~(OCI2C_CTRL_EN|OCI2C_CTRL_IEN));
+
+       return 0;
+}
+
+static int ocores_i2c_resume(struct platform_device *pdev)
+{
+       struct ocores_i2c *i2c = platform_get_drvdata(pdev);
+
+       ocores_init(i2c);
+
+       return 0;
+}
+#else
+#define ocores_i2c_suspend     NULL
+#define ocores_i2c_resume      NULL
+#endif
+
 /* work with hotplug and coldplug */
 MODULE_ALIAS("platform:ocores-i2c");
 
 static struct platform_driver ocores_i2c_driver = {
-       .probe  = ocores_i2c_probe,
-       .remove = __devexit_p(ocores_i2c_remove),
-       .driver = {
+       .probe   = ocores_i2c_probe,
+       .remove  = __devexit_p(ocores_i2c_remove),
+       .suspend = ocores_i2c_suspend,
+       .resume  = ocores_i2c_resume,
+       .driver  = {
                .owner = THIS_MODULE,
                .name = "ocores-i2c",
        },
index 1603c81e39d472e0b45644477db450aa3e26382e..adf0fbb902f0850fb77a77b2bdee30a6bff7e206 100644 (file)
@@ -365,7 +365,7 @@ static int __devinit pasemi_smb_probe(struct pci_dev *dev,
        smbus->adapter.owner = THIS_MODULE;
        snprintf(smbus->adapter.name, sizeof(smbus->adapter.name),
                 "PA Semi SMBus adapter at 0x%lx", smbus->base);
-       smbus->adapter.class = I2C_CLASS_HWMON;
+       smbus->adapter.class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        smbus->adapter.algo = &smbus_algorithm;
        smbus->adapter.algo_data = smbus;
        smbus->adapter.nr = PCI_FUNC(dev->devfn);
index 9d75f51e8f0efe648a22ff3ec33d231b42888167..6bb15ad0a6b6bc4c183eac4029220bf7355e2b53 100644 (file)
@@ -163,7 +163,7 @@ static int __devinit i2c_pca_pf_probe(struct platform_device *pdev)
 
        i2c->reg_base = ioremap(res->start, res_len(res));
        if (!i2c->reg_base) {
-               ret = -EIO;
+               ret = -ENOMEM;
                goto e_remap;
        }
        i2c->io_base = res->start;
index ac916596858764481f08afdde261b770be1a1b54..eaa9b387543e8730fec9c1e3d247ae52f6d4640a 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    piix4.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
     Copyright (c) 1998 - 2002 Frodo Looijaard <frodol@dds.nl> and
     Philip Edelbrock <phil@netroedge.com>
 
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/dmi.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 
-struct sd {
-       const unsigned short mfr;
-       const unsigned short dev;
-       const unsigned char fn;
-       const char *name;
-};
-
 /* PIIX4 SMBus address offsets */
 #define SMBHSTSTS      (0 + piix4_smba)
 #define SMBHSLVSTS     (1 + piix4_smba)
@@ -101,8 +93,6 @@ MODULE_PARM_DESC(force_addr,
                 "Forcibly enable the PIIX4 at the given address. "
                 "EXTREMELY DANGEROUS!");
 
-static int piix4_transaction(void);
-
 static unsigned short piix4_smba;
 static int srvrworks_csb5_delay;
 static struct pci_driver piix4_driver;
@@ -141,8 +131,6 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
 {
        unsigned char temp;
 
-       dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
-
        if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
            (PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5))
                srvrworks_csb5_delay = 1;
@@ -172,17 +160,20 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
                pci_read_config_word(PIIX4_dev, SMBBA, &piix4_smba);
                piix4_smba &= 0xfff0;
                if(piix4_smba == 0) {
-                       dev_err(&PIIX4_dev->dev, "SMB base address "
+                       dev_err(&PIIX4_dev->dev, "SMBus base address "
                                "uninitialized - upgrade BIOS or use "
                                "force_addr=0xaddr\n");
                        return -ENODEV;
                }
        }
 
+       if (acpi_check_region(piix4_smba, SMBIOSIZE, piix4_driver.name))
+               return -EBUSY;
+
        if (!request_region(piix4_smba, SMBIOSIZE, piix4_driver.name)) {
-               dev_err(&PIIX4_dev->dev, "SMB region 0x%x already in use!\n",
+               dev_err(&PIIX4_dev->dev, "SMBus region 0x%x already in use!\n",
                        piix4_smba);
-               return -ENODEV;
+               return -EBUSY;
        }
 
        pci_read_config_byte(PIIX4_dev, SMBHSTCFG, &temp);
@@ -228,13 +219,13 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
                        "(or code out of date)!\n");
 
        pci_read_config_byte(PIIX4_dev, SMBREV, &temp);
-       dev_dbg(&PIIX4_dev->dev, "SMBREV = 0x%X\n", temp);
-       dev_dbg(&PIIX4_dev->dev, "SMBA = 0x%X\n", piix4_smba);
+       dev_info(&PIIX4_dev->dev,
+                "SMBus Host Controller at 0x%x, revision %d\n",
+                piix4_smba, temp);
 
        return 0;
 }
 
-/* Another internally used function */
 static int piix4_transaction(void)
 {
        int temp;
@@ -253,7 +244,7 @@ static int piix4_transaction(void)
                outb_p(temp, SMBHSTSTS);
                if ((temp = inb_p(SMBHSTSTS)) != 0x00) {
                        dev_err(&piix4_adapter.dev, "Failed! (%02x)\n", temp);
-                       return -1;
+                       return -EBUSY;
                } else {
                        dev_dbg(&piix4_adapter.dev, "Successful!\n");
                }
@@ -275,23 +266,23 @@ static int piix4_transaction(void)
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
                dev_err(&piix4_adapter.dev, "SMBus Timeout!\n");
-               result = -1;
+               result = -ETIMEDOUT;
        }
 
        if (temp & 0x10) {
-               result = -1;
+               result = -EIO;
                dev_err(&piix4_adapter.dev, "Error: Failed bus transaction\n");
        }
 
        if (temp & 0x08) {
-               result = -1;
+               result = -EIO;
                dev_dbg(&piix4_adapter.dev, "Bus collision! SMBus may be "
                        "locked until next hard reset. (sorry!)\n");
                /* Clock stops and slave is stuck in mid-transmission */
        }
 
        if (temp & 0x04) {
-               result = -1;
+               result = -ENXIO;
                dev_dbg(&piix4_adapter.dev, "Error: no response!\n");
        }
 
@@ -309,31 +300,29 @@ static int piix4_transaction(void)
        return result;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                 unsigned short flags, char read_write,
                 u8 command, int size, union i2c_smbus_data * data)
 {
        int i, len;
+       int status;
 
        switch (size) {
-       case I2C_SMBUS_PROC_CALL:
-               dev_err(&adap->dev, "I2C_SMBUS_PROC_CALL not supported!\n");
-               return -1;
        case I2C_SMBUS_QUICK:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+               outb_p((addr << 1) | read_write,
                       SMBHSTADD);
                size = PIIX4_QUICK;
                break;
        case I2C_SMBUS_BYTE:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+               outb_p((addr << 1) | read_write,
                       SMBHSTADD);
                if (read_write == I2C_SMBUS_WRITE)
                        outb_p(command, SMBHSTCMD);
                size = PIIX4_BYTE;
                break;
        case I2C_SMBUS_BYTE_DATA:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+               outb_p((addr << 1) | read_write,
                       SMBHSTADD);
                outb_p(command, SMBHSTCMD);
                if (read_write == I2C_SMBUS_WRITE)
@@ -341,7 +330,7 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                size = PIIX4_BYTE_DATA;
                break;
        case I2C_SMBUS_WORD_DATA:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+               outb_p((addr << 1) | read_write,
                       SMBHSTADD);
                outb_p(command, SMBHSTCMD);
                if (read_write == I2C_SMBUS_WRITE) {
@@ -351,15 +340,13 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                size = PIIX4_WORD_DATA;
                break;
        case I2C_SMBUS_BLOCK_DATA:
-               outb_p(((addr & 0x7f) << 1) | (read_write & 0x01),
+               outb_p((addr << 1) | read_write,
                       SMBHSTADD);
                outb_p(command, SMBHSTCMD);
                if (read_write == I2C_SMBUS_WRITE) {
                        len = data->block[0];
-                       if (len < 0)
-                               len = 0;
-                       if (len > 32)
-                               len = 32;
+                       if (len == 0 || len > I2C_SMBUS_BLOCK_MAX)
+                               return -EINVAL;
                        outb_p(len, SMBHSTDAT0);
                        i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
                        for (i = 1; i <= len; i++)
@@ -367,12 +354,16 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                }
                size = PIIX4_BLOCK_DATA;
                break;
+       default:
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
        }
 
        outb_p((size & 0x1C) + (ENABLE_INT9 & 1), SMBHSTCNT);
 
-       if (piix4_transaction())        /* Error in transaction */
-               return -1;
+       status = piix4_transaction();
+       if (status)
+               return status;
 
        if ((read_write == I2C_SMBUS_WRITE) || (size == PIIX4_QUICK))
                return 0;
@@ -388,6 +379,8 @@ static s32 piix4_access(struct i2c_adapter * adap, u16 addr,
                break;
        case PIIX4_BLOCK_DATA:
                data->block[0] = inb_p(SMBHSTDAT0);
+               if (data->block[0] == 0 || data->block[0] > I2C_SMBUS_BLOCK_MAX)
+                       return -EPROTO;
                i = inb_p(SMBHSTCNT);   /* Reset SMBBLKDAT */
                for (i = 1; i <= data->block[0]; i++)
                        data->block[i] = inb_p(SMBBLKDAT);
@@ -411,7 +404,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter piix4_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_PIIX4,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
index 63b3e2c11cff1a17ac67b2b21b39d49851c5143a..dcf2045b5222b44aac99b568f7170701ecf0ae78 100644 (file)
@@ -622,7 +622,7 @@ static struct i2c_algorithm pmcmsptwi_algo = {
 
 static struct i2c_adapter pmcmsptwi_adapter = {
        .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &pmcmsptwi_algo,
        .name           = DRV_NAME,
 };
diff --git a/drivers/i2c/busses/i2c-prosavage.c b/drivers/i2c/busses/i2c-prosavage.c
deleted file mode 100644 (file)
index 07c1f1e..0000000
+++ /dev/null
@@ -1,325 +0,0 @@
-/*
- *    kernel/busses/i2c-prosavage.c
- *
- *    i2c bus driver for S3/VIA 8365/8375 graphics processor.
- *    Copyright (c) 2003 Henk Vergonet <henk@god.dyndns.org>
- *    Based on code written by:
- *     Frodo Looijaard <frodol@dds.nl>,
- *     Philip Edelbrock <phil@netroedge.com>,
- *     Ralph Metzler <rjkm@thp.uni-koeln.de>, and
- *     Mark D. Studebaker <mdsxyz123@yahoo.com>
- *     Simon Vogl
- *     and others
- *
- *    Please read the lm_sensors documentation for details on use.
- *
- *    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.
- *
- */
-/*  18-05-2003 HVE - created
- *  14-06-2003 HVE - adapted for lm_sensors2
- *  17-06-2003 HVE - linux 2.5.xx compatible
- *  18-06-2003 HVE - codingstyle
- *  21-06-2003 HVE - compatibility lm_sensors2 and linux 2.5.xx
- *                  codingstyle, mmio enabled
- *
- *  This driver interfaces to the I2C bus of the VIA north bridge embedded
- *  ProSavage4/8 devices. Usefull for gaining access to the TV Encoder chips.
- *
- *  Graphics cores:
- *   S3/VIA KM266/VT8375 aka ProSavage8
- *   S3/VIA KM133/VT8365 aka Savage4
- *
- *  Two serial busses are implemented:
- *   SERIAL1 - I2C serial communications interface
- *   SERIAL2 - DDC2 monitor communications interface
- *
- *  Tested on a FX41 mainboard, see http://www.shuttle.com
- * 
- *
- *  TODO:
- *  - integration with prosavage framebuffer device
- *    (Additional documentation needed :(
- */
-
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <asm/io.h>
-
-/*
- * driver configuration
- */
-#define MAX_BUSSES     2
-
-struct s_i2c_bus {
-       void __iomem *mmvga;
-       int     i2c_reg;
-       int     adap_ok;
-       struct i2c_adapter              adap;
-       struct i2c_algo_bit_data        algo;
-};
-
-struct s_i2c_chip {
-       void __iomem *mmio;
-       struct s_i2c_bus        i2c_bus[MAX_BUSSES];
-};
-
-
-/*
- * i2c configuration
- */
-#define CYCLE_DELAY    10
-#define TIMEOUT                (HZ / 2)
-
-
-/* 
- * S3/VIA 8365/8375 registers
- */
-#define VGA_CR_IX      0x3d4
-#define VGA_CR_DATA    0x3d5
-
-#define CR_SERIAL1     0xa0    /* I2C serial communications interface */
-#define MM_SERIAL1     0xff20
-#define CR_SERIAL2     0xb1    /* DDC2 monitor communications interface */
-
-/* based on vt8365 documentation */
-#define I2C_ENAB       0x10
-#define I2C_SCL_OUT    0x01
-#define I2C_SDA_OUT    0x02
-#define I2C_SCL_IN     0x04
-#define I2C_SDA_IN     0x08
-
-#define SET_CR_IX(p, val)      writeb((val), (p)->mmvga + VGA_CR_IX)
-#define SET_CR_DATA(p, val)    writeb((val), (p)->mmvga + VGA_CR_DATA)
-#define GET_CR_DATA(p)         readb((p)->mmvga + VGA_CR_DATA)
-
-
-/*
- * Serial bus line handling
- *
- * serial communications register as parameter in private data
- *
- * TODO: locks with other code sections accessing video registers?
- */
-static void bit_s3via_setscl(void *bus, int val)
-{
-       struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
-       unsigned int r;
-
-       SET_CR_IX(p, p->i2c_reg);
-       r = GET_CR_DATA(p);
-       r |= I2C_ENAB;
-       if (val) {
-               r |= I2C_SCL_OUT;
-       } else {
-               r &= ~I2C_SCL_OUT;
-       }
-       SET_CR_DATA(p, r);
-}
-
-static void bit_s3via_setsda(void *bus, int val)
-{
-       struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
-       unsigned int r;
-       
-       SET_CR_IX(p, p->i2c_reg);
-       r = GET_CR_DATA(p);
-       r |= I2C_ENAB;
-       if (val) {
-               r |= I2C_SDA_OUT;
-       } else {
-               r &= ~I2C_SDA_OUT;
-       }
-       SET_CR_DATA(p, r);
-}
-
-static int bit_s3via_getscl(void *bus)
-{
-       struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
-
-       SET_CR_IX(p, p->i2c_reg);
-       return (0 != (GET_CR_DATA(p) & I2C_SCL_IN));
-}
-
-static int bit_s3via_getsda(void *bus)
-{
-       struct s_i2c_bus *p = (struct s_i2c_bus *)bus;
-
-       SET_CR_IX(p, p->i2c_reg);
-       return (0 != (GET_CR_DATA(p) & I2C_SDA_IN));
-}
-
-
-/*
- * adapter initialisation
- */
-static int i2c_register_bus(struct pci_dev *dev, struct s_i2c_bus *p, void __iomem *mmvga, u32 i2c_reg)
-{
-       int ret;
-       p->adap.owner     = THIS_MODULE;
-       p->adap.id        = I2C_HW_B_S3VIA;
-       p->adap.algo_data = &p->algo;
-       p->adap.dev.parent = &dev->dev;
-       p->algo.setsda    = bit_s3via_setsda;
-       p->algo.setscl    = bit_s3via_setscl;
-       p->algo.getsda    = bit_s3via_getsda;
-       p->algo.getscl    = bit_s3via_getscl;
-       p->algo.udelay    = CYCLE_DELAY;
-       p->algo.timeout   = TIMEOUT;
-       p->algo.data      = p;
-       p->mmvga          = mmvga;
-       p->i2c_reg        = i2c_reg;
-    
-       ret = i2c_bit_add_bus(&p->adap);
-       if (ret) {
-               return ret;
-       }
-
-       p->adap_ok = 1;
-       return 0;
-}
-
-
-/*
- * Cleanup stuff
- */
-static void prosavage_remove(struct pci_dev *dev)
-{
-       struct s_i2c_chip *chip;
-       int i, ret;
-
-       chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
-
-       if (!chip) {
-               return;
-       }
-       for (i = MAX_BUSSES - 1; i >= 0; i--) {
-               if (chip->i2c_bus[i].adap_ok == 0)
-                       continue;
-
-               ret = i2c_del_adapter(&chip->i2c_bus[i].adap);
-               if (ret) {
-                       dev_err(&dev->dev, "%s not removed\n",
-                               chip->i2c_bus[i].adap.name);
-               }
-       }
-       if (chip->mmio) {
-               iounmap(chip->mmio);
-       }
-       kfree(chip);
-}
-
-
-/*
- * Detect chip and initialize it
- */
-static int __devinit prosavage_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       int ret;
-       unsigned long base, len;
-       struct s_i2c_chip *chip;
-       struct s_i2c_bus  *bus;
-
-       pci_set_drvdata(dev, kzalloc(sizeof(struct s_i2c_chip), GFP_KERNEL));
-       chip = (struct s_i2c_chip *)pci_get_drvdata(dev);
-       if (chip == NULL) {
-               return -ENOMEM;
-       }
-
-       base = dev->resource[0].start & PCI_BASE_ADDRESS_MEM_MASK;
-       len  = dev->resource[0].end - base + 1;
-       chip->mmio = ioremap_nocache(base, len);
-
-       if (chip->mmio == NULL) {
-               dev_err(&dev->dev, "ioremap failed\n");
-               prosavage_remove(dev);
-               return -ENODEV;
-       }
-
-
-       /*
-        * Chip initialisation
-        */
-       /* Unlock Extended IO Space ??? */
-
-
-       /*
-        * i2c bus registration
-        */
-       bus = &chip->i2c_bus[0];
-       snprintf(bus->adap.name, sizeof(bus->adap.name),
-               "ProSavage I2C bus at %02x:%02x.%x",
-               dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-       ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL1);
-       if (ret) {
-               goto err_adap;
-       }
-       /*
-        * ddc bus registration
-        */
-       bus = &chip->i2c_bus[1];
-       snprintf(bus->adap.name, sizeof(bus->adap.name),
-               "ProSavage DDC bus at %02x:%02x.%x",
-               dev->bus->number, PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
-       ret = i2c_register_bus(dev, bus, chip->mmio + 0x8000, CR_SERIAL2);
-       if (ret) {
-               goto err_adap;
-       }
-       return 0;
-err_adap:
-       dev_err(&dev->dev, "%s failed\n", bus->adap.name);
-       prosavage_remove(dev);
-       return ret;
-}
-
-
-/*
- * Data for PCI driver interface
- */
-static struct pci_device_id prosavage_pci_tbl[] = {
-       { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_SAVAGE4) },
-       { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_DEVICE_ID_S3_PROSAVAGE8) },
-       { 0, },
-};
-
-MODULE_DEVICE_TABLE (pci, prosavage_pci_tbl);
-
-static struct pci_driver prosavage_driver = {
-       .name           =       "prosavage_smbus",
-       .id_table       =       prosavage_pci_tbl,
-       .probe          =       prosavage_probe,
-       .remove         =       prosavage_remove,
-};
-
-static int __init i2c_prosavage_init(void)
-{
-       return pci_register_driver(&prosavage_driver);
-}
-
-static void __exit i2c_prosavage_exit(void)
-{
-       pci_unregister_driver(&prosavage_driver);
-}
-
-MODULE_DEVICE_TABLE(pci, prosavage_pci_tbl);
-MODULE_AUTHOR("Henk Vergonet");
-MODULE_DESCRIPTION("ProSavage VIA 8365/8375 smbus driver");
-MODULE_LICENSE("GPL");
-
-module_init (i2c_prosavage_init);
-module_exit (i2c_prosavage_exit);
index dde6ce963a1963efeeeecb284ad4031a0275bc2d..af9e6034d7fbda7c51ce0925a7a0707d974d82a1 100644 (file)
@@ -1104,5 +1104,5 @@ static void __exit i2c_adap_pxa_exit(void)
 MODULE_LICENSE("GPL");
 MODULE_ALIAS("platform:pxa2xx-i2c");
 
-module_init(i2c_adap_pxa_init);
+subsys_initcall(i2c_adap_pxa_init);
 module_exit(i2c_adap_pxa_exit);
index 9e8c875437bec533ec4e32579602f31f4336bbe9..007390ad9810555b0fe7f2ba6077445601ec919b 100644 (file)
@@ -590,7 +590,7 @@ static struct s3c24xx_i2c s3c24xx_i2c = {
                .owner                  = THIS_MODULE,
                .algo                   = &s3c24xx_i2c_algorithm,
                .retries                = 2,
-               .class                  = I2C_CLASS_HWMON,
+               .class                  = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        },
 };
 
diff --git a/drivers/i2c/busses/i2c-savage4.c b/drivers/i2c/busses/i2c-savage4.c
deleted file mode 100644 (file)
index 8adf4ab..0000000
+++ /dev/null
@@ -1,185 +0,0 @@
-/*
-    i2c-savage4.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
-    Copyright (C) 1998-2003  The LM Sensors Team
-    Alexander Wold <awold@bigfoot.com>
-    Mark D. Studebaker <mdsxyz123@yahoo.com>
-    
-    Based on i2c-voodoo3.c.
-
-    This program is free software; you can redistribute it and/or modify
-    it under the terms of the GNU General Public License as published by
-    the Free Software Foundation; either version 2 of the License, or
-    (at your option) any later version.
-
-    This program is distributed in the hope that it will be useful,
-    but WITHOUT ANY WARRANTY; without even the implied warranty of
-    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
-    GNU General Public License for more details.
-
-    You should have received a copy of the GNU General Public License
-    along with this program; if not, write to the Free Software
-    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-/* This interfaces to the I2C bus of the Savage4 to gain access to
-   the BT869 and possibly other I2C devices. The DDC bus is not
-   yet supported because its register is not memory-mapped.
-*/
-
-#include <linux/kernel.h>
-#include <linux/module.h>
-#include <linux/init.h>
-#include <linux/pci.h>
-#include <linux/i2c.h>
-#include <linux/i2c-algo-bit.h>
-#include <asm/io.h>
-
-/* device IDs */
-#define PCI_CHIP_SAVAGE4       0x8A22
-#define PCI_CHIP_SAVAGE2000    0x9102
-
-#define REG                    0xff20  /* Serial Port 1 Register */
-
-/* bit locations in the register */
-#define I2C_ENAB               0x00000020
-#define I2C_SCL_OUT            0x00000001
-#define I2C_SDA_OUT            0x00000002
-#define I2C_SCL_IN             0x00000008
-#define I2C_SDA_IN             0x00000010
-
-/* delays */
-#define CYCLE_DELAY            10
-#define TIMEOUT                        (HZ / 2)
-
-
-static void __iomem *ioaddr;
-
-/* The sav GPIO registers don't have individual masks for each bit
-   so we always have to read before writing. */
-
-static void bit_savi2c_setscl(void *data, int val)
-{
-       unsigned int r;
-       r = readl(ioaddr + REG);
-       if(val)
-               r |= I2C_SCL_OUT;
-       else
-               r &= ~I2C_SCL_OUT;
-       writel(r, ioaddr + REG);
-       readl(ioaddr + REG);    /* flush posted write */
-}
-
-static void bit_savi2c_setsda(void *data, int val)
-{
-       unsigned int r;
-       r = readl(ioaddr + REG);
-       if(val)
-               r |= I2C_SDA_OUT;
-       else
-               r &= ~I2C_SDA_OUT;
-       writel(r, ioaddr + REG);
-       readl(ioaddr + REG);    /* flush posted write */
-}
-
-/* The GPIO pins are open drain, so the pins always remain outputs.
-   We rely on the i2c-algo-bit routines to set the pins high before
-   reading the input from other chips. */
-
-static int bit_savi2c_getscl(void *data)
-{
-       return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
-}
-
-static int bit_savi2c_getsda(void *data)
-{
-       return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
-}
-
-/* Configures the chip */
-
-static int config_s4(struct pci_dev *dev)
-{
-       unsigned long cadr;
-
-       /* map memory */
-       cadr = dev->resource[0].start;
-       cadr &= PCI_BASE_ADDRESS_MEM_MASK;
-       ioaddr = ioremap_nocache(cadr, 0x0080000);
-       if (ioaddr) {
-               /* writel(0x8160, ioaddr + REG2); */
-               writel(0x00000020, ioaddr + REG);
-               dev_info(&dev->dev, "Using Savage4 at %p\n", ioaddr);
-               return 0;
-       }
-       return -ENODEV;
-}
-
-static struct i2c_algo_bit_data sav_i2c_bit_data = {
-       .setsda         = bit_savi2c_setsda,
-       .setscl         = bit_savi2c_setscl,
-       .getsda         = bit_savi2c_getsda,
-       .getscl         = bit_savi2c_getscl,
-       .udelay         = CYCLE_DELAY,
-       .timeout        = TIMEOUT
-};
-
-static struct i2c_adapter savage4_i2c_adapter = {
-       .owner          = THIS_MODULE,
-       .id             = I2C_HW_B_SAVAGE,
-       .name           = "I2C Savage4 adapter",
-       .algo_data      = &sav_i2c_bit_data,
-};
-
-static struct pci_device_id savage4_ids[] __devinitdata = {
-       { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE4) },
-       { PCI_DEVICE(PCI_VENDOR_ID_S3, PCI_CHIP_SAVAGE2000) },
-       { 0, }
-};
-
-MODULE_DEVICE_TABLE (pci, savage4_ids);
-
-static int __devinit savage4_probe(struct pci_dev *dev, const struct pci_device_id *id)
-{
-       int retval;
-
-       retval = config_s4(dev);
-       if (retval)
-               return retval;
-
-       /* set up the sysfs linkage to our parent device */
-       savage4_i2c_adapter.dev.parent = &dev->dev;
-
-       return i2c_bit_add_bus(&savage4_i2c_adapter);
-}
-
-static void __devexit savage4_remove(struct pci_dev *dev)
-{
-       i2c_del_adapter(&savage4_i2c_adapter);
-       iounmap(ioaddr);
-}
-
-static struct pci_driver savage4_driver = {
-       .name           = "savage4_smbus",
-       .id_table       = savage4_ids,
-       .probe          = savage4_probe,
-       .remove         = __devexit_p(savage4_remove),
-};
-
-static int __init i2c_savage4_init(void)
-{
-       return pci_register_driver(&savage4_driver);
-}
-
-static void __exit i2c_savage4_exit(void)
-{
-       pci_unregister_driver(&savage4_driver);
-}
-
-MODULE_AUTHOR("Alexander Wold <awold@bigfoot.com> "
-               "and Mark D. Studebaker <mdsxyz123@yahoo.com>");
-MODULE_DESCRIPTION("Savage4 I2C/SMBus driver");
-MODULE_LICENSE("GPL");
-
-module_init(i2c_savage4_init);
-module_exit(i2c_savage4_exit);
index 114634da6c6e9f3a7bd7ca77bf04476fc1c2818c..4ddefbf238e97f797a5a4627d7887ab4357b3af2 100644 (file)
@@ -143,7 +143,7 @@ static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
        csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
        csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
 
-       return i2c_add_adapter(i2c_adap);
+       return i2c_add_numbered_adapter(i2c_adap);
 }
 
 
@@ -156,17 +156,19 @@ static struct i2c_adapter sibyte_board_adapter[2] = {
        {
                .owner          = THIS_MODULE,
                .id             = I2C_HW_SIBYTE,
-               .class          = I2C_CLASS_HWMON,
+               .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
                .algo           = NULL,
                .algo_data      = &sibyte_board_data[0],
+               .nr             = 0,
                .name           = "SiByte SMBus 0",
        },
        {
                .owner          = THIS_MODULE,
                .id             = I2C_HW_SIBYTE,
-               .class          = I2C_CLASS_HWMON,
+               .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
                .algo           = NULL,
                .algo_data      = &sibyte_board_data[1],
+               .nr             = 1,
                .name           = "SiByte SMBus 1",
        },
 };
index 9ca8f9155f958c40378a50770eb3327a0702c2e6..dfc2d5eb6a6895f437abcbb7f19ada78f815e618 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    sis5595.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
     Philip Edelbrock <phil@netroedge.com>
 
@@ -62,6 +60,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 static int blacklist[] = {
@@ -174,6 +173,11 @@ static int sis5595_setup(struct pci_dev *SIS5595_dev)
 
        /* NB: We grab just the two SMBus registers here, but this may still
         * interfere with ACPI :-(  */
+       retval = acpi_check_region(sis5595_base + SMB_INDEX, 2,
+                                  sis5595_driver.name);
+       if (retval)
+               return retval;
+
        if (!request_region(sis5595_base + SMB_INDEX, 2,
                            sis5595_driver.name)) {
                dev_err(&SIS5595_dev->dev, "SMBus registers 0x%04x-0x%04x already in use!\n",
@@ -236,7 +240,7 @@ static int sis5595_transaction(struct i2c_adapter *adap)
                sis5595_write(SMB_STS_HI, temp >> 8);
                if ((temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8)) != 0x00) {
                        dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
-                       return -1;
+                       return -EBUSY;
                } else {
                        dev_dbg(&adap->dev, "Successful!\n");
                }
@@ -254,19 +258,19 @@ static int sis5595_transaction(struct i2c_adapter *adap)
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
                dev_dbg(&adap->dev, "SMBus Timeout!\n");
-               result = -1;
+               result = -ETIMEDOUT;
        }
 
        if (temp & 0x10) {
                dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
-               result = -1;
+               result = -ENXIO;
        }
 
        if (temp & 0x20) {
                dev_err(&adap->dev, "Bus collision! SMBus may be locked until "
                        "next hard reset (or not...)\n");
                /* Clock stops and slave is stuck in mid-transmission */
-               result = -1;
+               result = -EIO;
        }
 
        temp = sis5595_read(SMB_STS_LO) + (sis5595_read(SMB_STS_HI) << 8);
@@ -282,11 +286,13 @@ static int sis5595_transaction(struct i2c_adapter *adap)
        return result;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
                          unsigned short flags, char read_write,
                          u8 command, int size, union i2c_smbus_data *data)
 {
+       int status;
+
        switch (size) {
        case I2C_SMBUS_QUICK:
                sis5595_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
@@ -318,13 +324,14 @@ static s32 sis5595_access(struct i2c_adapter *adap, u16 addr,
                break;
        default:
                dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
-               return -1;
+               return -EOPNOTSUPP;
        }
 
        sis5595_write(SMB_CTL_LO, ((size & 0x0E)));
 
-       if (sis5595_transaction(adap))
-               return -1;
+       status = sis5595_transaction(adap);
+       if (status)
+               return status;
 
        if ((size != SIS5595_PROC_CALL) &&
            ((read_write == I2C_SMBUS_WRITE) || (size == SIS5595_QUICK)))
@@ -359,7 +366,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter sis5595_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_SIS5595,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
index 3765dd7f450f06e7c71f6623d67795c9e4cc056d..e7c4b790da5427393783405f6da6271b120efd64 100644 (file)
@@ -1,7 +1,4 @@
 /*
-    i2c-sis630.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
-
     Copyright (c) 2002,2003 Alexander Malysh <amalysh@web.de>
 
     This program is free software; you can redistribute it and/or modify
@@ -55,6 +52,7 @@
 #include <linux/ioport.h>
 #include <linux/init.h>
 #include <linux/i2c.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 /* SIS630 SMBus registers */
@@ -134,7 +132,7 @@ static int sis630_transaction_start(struct i2c_adapter *adap, int size, u8 *oldc
 
                if ((temp = sis630_read(SMB_CNT) & 0x03) != 0x00) {
                        dev_dbg(&adap->dev, "Failed! (%02x)\n", temp);
-                       return -1;
+                       return -EBUSY;
                 } else {
                        dev_dbg(&adap->dev, "Successful!\n");
                }
@@ -177,17 +175,17 @@ static int sis630_transaction_wait(struct i2c_adapter *adap, int size)
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
                dev_dbg(&adap->dev, "SMBus Timeout!\n");
-               result = -1;
+               result = -ETIMEDOUT;
        }
 
        if (temp & 0x02) {
                dev_dbg(&adap->dev, "Error: Failed bus transaction\n");
-               result = -1;
+               result = -ENXIO;
        }
 
        if (temp & 0x04) {
                dev_err(&adap->dev, "Bus collision!\n");
-               result = -1;
+               result = -EIO;
                /*
                  TBD: Datasheet say:
                  the software should clear this bit and restart SMBUS operation.
@@ -250,8 +248,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
                        if (i==8 || (len<8 && i==len)) {
                                dev_dbg(&adap->dev, "start trans len=%d i=%d\n",len ,i);
                                /* first transaction */
-                               if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock))
-                                       return -1;
+                               rc = sis630_transaction_start(adap,
+                                               SIS630_BLOCK_DATA, &oldclock);
+                               if (rc)
+                                       return rc;
                        }
                        else if ((i-1)%8 == 7 || i==len) {
                                dev_dbg(&adap->dev, "trans_wait len=%d i=%d\n",len,i);
@@ -264,9 +264,10 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
                                        */
                                        sis630_write(SMB_STS,0x10);
                                }
-                               if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
+                               rc = sis630_transaction_wait(adap,
+                                               SIS630_BLOCK_DATA);
+                               if (rc) {
                                        dev_dbg(&adap->dev, "trans_wait failed\n");
-                                       rc = -1;
                                        break;
                                }
                        }
@@ -275,13 +276,14 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
        else {
                /* read request */
                data->block[0] = len = 0;
-               if (sis630_transaction_start(adap, SIS630_BLOCK_DATA, &oldclock)) {
-                       return -1;
-               }
+               rc = sis630_transaction_start(adap,
+                               SIS630_BLOCK_DATA, &oldclock);
+               if (rc)
+                       return rc;
                do {
-                       if (sis630_transaction_wait(adap, SIS630_BLOCK_DATA)) {
+                       rc = sis630_transaction_wait(adap, SIS630_BLOCK_DATA);
+                       if (rc) {
                                dev_dbg(&adap->dev, "trans_wait failed\n");
-                               rc = -1;
                                break;
                        }
                        /* if this first transaction then read byte count */
@@ -311,11 +313,13 @@ static int sis630_block_data(struct i2c_adapter *adap, union i2c_smbus_data *dat
        return rc;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
                         unsigned short flags, char read_write,
                         u8 command, int size, union i2c_smbus_data *data)
 {
+       int status;
+
        switch (size) {
                case I2C_SMBUS_QUICK:
                        sis630_write(SMB_ADDR, ((addr & 0x7f) << 1) | (read_write & 0x01));
@@ -350,13 +354,14 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
                        size = SIS630_BLOCK_DATA;
                        return sis630_block_data(adap, data, read_write);
                default:
-                       printk("Unsupported I2C size\n");
-                       return -1;
-                       break;
+                       dev_warn(&adap->dev, "Unsupported transaction %d\n",
+                                size);
+                       return -EOPNOTSUPP;
        }
 
-       if (sis630_transaction(adap, size))
-               return -1;
+       status = sis630_transaction(adap, size);
+       if (status)
+               return status;
 
        if ((size != SIS630_PCALL) &&
                ((read_write == I2C_SMBUS_WRITE) || (size == SIS630_QUICK))) {
@@ -372,9 +377,6 @@ static s32 sis630_access(struct i2c_adapter *adap, u16 addr,
                case SIS630_WORD_DATA:
                        data->word = sis630_read(SMB_BYTE) + (sis630_read(SMB_BYTE + 1) << 8);
                        break;
-               default:
-                       return -1;
-                       break;
        }
 
        return 0;
@@ -433,6 +435,11 @@ static int sis630_setup(struct pci_dev *sis630_dev)
 
        dev_dbg(&sis630_dev->dev, "ACPI base at 0x%04x\n", acpi_base);
 
+       retval = acpi_check_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
+                                  sis630_driver.name);
+       if (retval)
+               goto exit;
+
        /* Everything is happy, let's grab the memory and set things up. */
        if (!request_region(acpi_base + SMB_STS, SIS630_SMB_IOREGION,
                            sis630_driver.name)) {
@@ -458,7 +465,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter sis630_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_SIS630,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
index dc235bb8e24d448ae5f815ff45314bdea789d740..f1bba639664171a805bedf75bac802f71cef0927 100644 (file)
@@ -1,7 +1,4 @@
 /*
-    sis96x.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
-
     Copyright (c) 2003 Mark M. Hoffman <mhoffman@lightlink.com>
 
     This program is free software; you can redistribute it and/or modify
@@ -40,6 +37,7 @@
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 /* base address register in PCI config space */
@@ -111,7 +109,7 @@ static int sis96x_transaction(int size)
                /* check it again */
                if (((temp = sis96x_read(SMB_CNT)) & 0x03) != 0x00) {
                        dev_dbg(&sis96x_adapter.dev, "Failed (0x%02x)\n", temp);
-                       return -1;
+                       return -EBUSY;
                } else {
                        dev_dbg(&sis96x_adapter.dev, "Successful\n");
                }
@@ -136,19 +134,19 @@ static int sis96x_transaction(int size)
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
                dev_dbg(&sis96x_adapter.dev, "SMBus Timeout! (0x%02x)\n", temp);
-               result = -1;
+               result = -ETIMEDOUT;
        }
 
        /* device error - probably missing ACK */
        if (temp & 0x02) {
                dev_dbg(&sis96x_adapter.dev, "Failed bus transaction!\n");
-               result = -1;
+               result = -ENXIO;
        }
 
        /* bus collision */
        if (temp & 0x04) {
                dev_dbg(&sis96x_adapter.dev, "Bus collision!\n");
-               result = -1;
+               result = -EIO;
        }
 
        /* Finish up by resetting the bus */
@@ -161,11 +159,12 @@ static int sis96x_transaction(int size)
        return result;
 }
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
                         unsigned short flags, char read_write,
                         u8 command, int size, union i2c_smbus_data * data)
 {
+       int status;
 
        switch (size) {
        case I2C_SMBUS_QUICK:
@@ -200,20 +199,14 @@ static s32 sis96x_access(struct i2c_adapter * adap, u16 addr,
                        SIS96x_PROC_CALL : SIS96x_WORD_DATA);
                break;
 
-       case I2C_SMBUS_BLOCK_DATA:
-               /* TO DO: */
-               dev_info(&adap->dev, "SMBus block not implemented!\n");
-               return -1;
-               break;
-
        default:
-               dev_info(&adap->dev, "Unsupported I2C size\n");
-               return -1;
-               break;
+               dev_warn(&adap->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
        }
 
-       if (sis96x_transaction(size))
-               return -1;
+       status = sis96x_transaction(size);
+       if (status)
+               return status;
 
        if ((size != SIS96x_PROC_CALL) &&
                ((read_write == I2C_SMBUS_WRITE) || (size == SIS96x_QUICK)))
@@ -249,7 +242,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter sis96x_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_SIS96X,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
@@ -286,6 +279,10 @@ static int __devinit sis96x_probe(struct pci_dev *dev,
        dev_info(&dev->dev, "SiS96x SMBus base address: 0x%04x\n",
                        sis96x_smbus_base);
 
+       retval = acpi_check_resource_conflict(&dev->resource[SIS96x_BAR]);
+       if (retval)
+               return retval;
+
        /* Everything is happy, let's grab the memory and set things up. */
        if (!request_region(sis96x_smbus_base, SMB_IOSIZE,
                            sis96x_driver.name)) {
index d08eeec53913ce9759a74e82b984bdc06dcf18b8..1b7b2af94036ca448ff226f49bd1e14ff45068c4 100644 (file)
@@ -43,7 +43,7 @@ struct stub_chip {
 
 static struct stub_chip *stub_chips;
 
-/* Return -1 on error. */
+/* Return negative errno on error. */
 static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
        char read_write, u8 command, int size, union i2c_smbus_data * data)
 {
@@ -120,7 +120,7 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
 
        default:
                dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
-               ret = -1;
+               ret = -EOPNOTSUPP;
                break;
        } /* switch (size) */
 
@@ -140,7 +140,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 
 static struct i2c_adapter stub_adapter = {
        .owner          = THIS_MODULE,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
        .name           = "SMBus stub driver",
 };
index de9db49e54d93d8785f0beef0df4c5df28036a12..224aa12ee7c85d880118db61cac79a2b564e6af1 100644 (file)
@@ -96,9 +96,8 @@ static int taos_smbus_xfer(struct i2c_adapter *adapter, u16 addr,
                        sprintf(p, "$%02X", command);
                break;
        default:
-               dev_dbg(&adapter->dev, "Unsupported transaction size %d\n",
-                       size);
-               return -EINVAL;
+               dev_warn(&adapter->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
        }
 
        /* Send the transaction to the TAOS EVM */
index 61716f6b14dcd2435c1b65f0fe27e05fc4f090cb..29cef0433f34d8a445078e695c600461bdfc0cc6 100644 (file)
@@ -1,7 +1,4 @@
 /*
-    i2c-via.c - Part of lm_sensors,  Linux kernel modules
-                for hardware monitoring
-
     i2c Support for Via Technologies 82C586B South Bridge
 
     Copyright (c) 1998, 1999 Kyösti Mälkki <kmalkki@cc.hut.fi>
@@ -87,7 +84,7 @@ static struct i2c_algo_bit_data bit_data = {
 static struct i2c_adapter vt586b_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_B_VIA,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .name           = "VIA i2c",
        .algo_data      = &bit_data,
 };
index 77b13d027f86336a08eda1d6e8110131aff1d84e..862eb352a2d92b9708cdad16adfec687fdc4dece 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    i2c-viapro.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
     Copyright (c) 1998 - 2002  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>, Kyösti Mälkki <kmalkki@cc.hut.fi>,
     Mark D. Studebaker <mdsxyz123@yahoo.com>
@@ -50,6 +48,7 @@
 #include <linux/ioport.h>
 #include <linux/i2c.h>
 #include <linux/init.h>
+#include <linux/acpi.h>
 #include <asm/io.h>
 
 static struct pci_dev *vt596_pdev;
@@ -152,7 +151,7 @@ static int vt596_transaction(u8 size)
                if ((temp = inb_p(SMBHSTSTS)) & 0x1F) {
                        dev_err(&vt596_adapter.dev, "SMBus reset failed! "
                                "(0x%02x)\n", temp);
-                       return -1;
+                       return -EBUSY;
                }
        }
 
@@ -167,24 +166,24 @@ static int vt596_transaction(u8 size)
 
        /* If the SMBus is still busy, we give up */
        if (timeout >= MAX_TIMEOUT) {
-               result = -1;
+               result = -ETIMEDOUT;
                dev_err(&vt596_adapter.dev, "SMBus timeout!\n");
        }
 
        if (temp & 0x10) {
-               result = -1;
+               result = -EIO;
                dev_err(&vt596_adapter.dev, "Transaction failed (0x%02x)\n",
                        size);
        }
 
        if (temp & 0x08) {
-               result = -1;
+               result = -EIO;
                dev_err(&vt596_adapter.dev, "SMBus collision!\n");
        }
 
        if (temp & 0x04) {
                int read = inb_p(SMBHSTADD) & 0x01;
-               result = -1;
+               result = -ENXIO;
                /* The quick and receive byte commands are used to probe
                   for chips, so errors are expected, and we don't want
                   to frighten the user. */
@@ -202,12 +201,13 @@ static int vt596_transaction(u8 size)
        return result;
 }
 
-/* Return -1 on error, 0 on success */
+/* Return negative errno on error, 0 on success */
 static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
                unsigned short flags, char read_write, u8 command,
                int size, union i2c_smbus_data *data)
 {
        int i;
+       int status;
 
        switch (size) {
        case I2C_SMBUS_QUICK:
@@ -258,8 +258,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
 
        outb_p(((addr & 0x7f) << 1) | read_write, SMBHSTADD);
 
-       if (vt596_transaction(size)) /* Error in transaction */
-               return -1;
+       status = vt596_transaction(size);
+       if (status)
+               return status;
 
        if ((read_write == I2C_SMBUS_WRITE) || (size == VT596_QUICK))
                return 0;
@@ -285,9 +286,9 @@ static s32 vt596_access(struct i2c_adapter *adap, u16 addr,
        return 0;
 
 exit_unsupported:
-       dev_warn(&vt596_adapter.dev, "Unsupported command invoked! (0x%02x)\n",
+       dev_warn(&vt596_adapter.dev, "Unsupported transaction %d\n",
                 size);
-       return -1;
+       return -EOPNOTSUPP;
 }
 
 static u32 vt596_func(struct i2c_adapter *adapter)
@@ -309,7 +310,7 @@ static const struct i2c_algorithm smbus_algorithm = {
 static struct i2c_adapter vt596_adapter = {
        .owner          = THIS_MODULE,
        .id             = I2C_HW_SMBUS_VIA2,
-       .class          = I2C_CLASS_HWMON,
+       .class          = I2C_CLASS_HWMON | I2C_CLASS_SPD,
        .algo           = &smbus_algorithm,
 };
 
@@ -354,6 +355,10 @@ static int __devinit vt596_probe(struct pci_dev *pdev,
        }
 
 found:
+       error = acpi_check_region(vt596_smba, 8, vt596_driver.name);
+       if (error)
+               return error;
+
        if (!request_region(vt596_smba, 8, vt596_driver.name)) {
                dev_err(&pdev->dev, "SMBus region 0x%x already in use!\n",
                        vt596_smba);
index 88a3447e11e1eaf47fb9ddc0b29fc0ab8fb0048f..1d4ae26ba73d7d2cab02e02f82d50688f5b99f2f 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    voodoo3.c - Part of lm_sensors, Linux kernel modules for hardware
-              monitoring
     Copyright (c) 1998, 1999  Frodo Looijaard <frodol@dds.nl>,
     Philip Edelbrock <phil@netroedge.com>,
     Ralph Metzler <rjkm@thp.uni-koeln.de>, and
index 61abe0f33255291ffa7e274f0aed3a8f68f283d6..ed794b145a115bb4d235ded80ffd66dfc3e67668 100644 (file)
@@ -442,7 +442,7 @@ static __init struct scx200_acb_iface *scx200_create_iface(const char *text,
        adapter->owner = THIS_MODULE;
        adapter->id = I2C_HW_SMBUS_SCX200;
        adapter->algo = &scx200_acb_algorithm;
-       adapter->class = I2C_CLASS_HWMON;
+       adapter->class = I2C_CLASS_HWMON | I2C_CLASS_SPD;
        adapter->dev.parent = dev;
 
        mutex_init(&iface->mutex);
index 2da2edfa68ec1ebf0954cfc48b9ea87fd3e50d26..50e0a465374193d6f93d4ceb3e74367c0a0b2ec7 100644 (file)
@@ -14,6 +14,32 @@ config DS1682
          This driver can also be built as a module.  If so, the module
          will be called ds1682.
 
+config AT24
+       tristate "EEPROMs from most vendors"
+       depends on SYSFS && EXPERIMENTAL
+       help
+         Enable this driver to get read/write support to most I2C EEPROMs,
+         after you configure the driver to know about each EEPROM on
+         your target board.  Use these generic chip names, instead of
+         vendor-specific ones like at24c64 or 24lc02:
+
+            24c00, 24c01, 24c02, spd (readonly 24c02), 24c04, 24c08,
+            24c16, 24c32, 24c64, 24c128, 24c256, 24c512, 24c1024
+
+         Unless you like data loss puzzles, always be sure that any chip
+         you configure as a 24c32 (32 kbit) or larger is NOT really a
+         24c16 (16 kbit) or smaller, and vice versa. Marking the chip
+         as read-only won't help recover from this. Also, if your chip
+         has any software write-protect mechanism you may want to review the
+         code to make sure this driver won't turn it on by accident.
+
+         If you use this with an SMBus adapter instead of an I2C adapter,
+         full functionality is not available.  Only smaller devices are
+         supported (24c16 and below, max 4 kByte).
+
+         This driver can also be built as a module.  If so, the module
+         will be called at24.
+
 config SENSORS_EEPROM
        tristate "EEPROM reader"
        depends on EXPERIMENTAL
@@ -26,8 +52,8 @@ config SENSORS_EEPROM
          will be called eeprom.
 
 config SENSORS_PCF8574
-       tristate "Philips PCF8574 and PCF8574A"
-       depends on EXPERIMENTAL
+       tristate "Philips PCF8574 and PCF8574A (DEPRECATED)"
+       depends on EXPERIMENTAL && GPIO_PCF857X = "n"
        default n
        help
          If you say yes here you get support for Philips PCF8574 and 
@@ -36,12 +62,16 @@ config SENSORS_PCF8574
          This driver can also be built as a module.  If so, the module
          will be called pcf8574.
 
+         This driver is deprecated and will be dropped soon. Use
+         drivers/gpio/pcf857x.c instead.
+
          These devices are hard to detect and rarely found on mainstream
          hardware.  If unsure, say N.
 
 config PCF8575
-       tristate "Philips PCF8575"
+       tristate "Philips PCF8575 (DEPRECATED)"
        default n
+       depends on GPIO_PCF857X = "n"
        help
          If you say yes here you get support for Philips PCF8575 chip.
          This chip is a 16-bit I/O expander for the I2C bus.  Several other
@@ -50,12 +80,15 @@ config PCF8575
          This driver can also be built as a module.  If so, the module
          will be called pcf8575.
 
+         This driver is deprecated and will be dropped soon. Use
+         drivers/gpio/pcf857x.c instead.
+
          This device is hard to detect and is rarely found on mainstream
          hardware.  If unsure, say N.
 
 config SENSORS_PCA9539
        tristate "Philips PCA9539 16-bit I/O port (DEPRECATED)"
-       depends on EXPERIMENTAL && GPIO_PCA9539 = "n"
+       depends on EXPERIMENTAL && GPIO_PCA953X = "n"
        help
          If you say yes here you get support for the Philips PCA9539
          16-bit I/O port.
@@ -64,7 +97,7 @@ config SENSORS_PCA9539
          will be called pca9539.
 
          This driver is deprecated and will be dropped soon. Use
-         drivers/gpio/pca9539.c instead.
+         drivers/gpio/pca953x.c instead.
 
 config SENSORS_PCF8591
        tristate "Philips PCF8591"
index e47aca0ca5aebda2bb70bc44d3f625a827301ea2..39e3e69ed1256bf93de0be16b9687bd15eb8e4a9 100644 (file)
@@ -10,6 +10,7 @@
 #
 
 obj-$(CONFIG_DS1682)           += ds1682.o
+obj-$(CONFIG_AT24)             += at24.o
 obj-$(CONFIG_SENSORS_EEPROM)   += eeprom.o
 obj-$(CONFIG_SENSORS_MAX6875)  += max6875.o
 obj-$(CONFIG_SENSORS_PCA9539)  += pca9539.o
diff --git a/drivers/i2c/chips/at24.c b/drivers/i2c/chips/at24.c
new file mode 100644 (file)
index 0000000..e764c94
--- /dev/null
@@ -0,0 +1,583 @@
+/*
+ * at24.c - handle most I2C EEPROMs
+ *
+ * Copyright (C) 2005-2007 David Brownell
+ * Copyright (C) 2008 Wolfram Sang, Pengutronix
+ *
+ * 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.
+ */
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/slab.h>
+#include <linux/delay.h>
+#include <linux/mutex.h>
+#include <linux/sysfs.h>
+#include <linux/mod_devicetable.h>
+#include <linux/log2.h>
+#include <linux/bitops.h>
+#include <linux/jiffies.h>
+#include <linux/i2c.h>
+#include <linux/i2c/at24.h>
+
+/*
+ * I2C EEPROMs from most vendors are inexpensive and mostly interchangeable.
+ * Differences between different vendor product lines (like Atmel AT24C or
+ * MicroChip 24LC, etc) won't much matter for typical read/write access.
+ * There are also I2C RAM chips, likewise interchangeable. One example
+ * would be the PCF8570, which acts like a 24c02 EEPROM (256 bytes).
+ *
+ * However, misconfiguration can lose data. "Set 16-bit memory address"
+ * to a part with 8-bit addressing will overwrite data. Writing with too
+ * big a page size also loses data. And it's not safe to assume that the
+ * conventional addresses 0x50..0x57 only hold eeproms; a PCF8563 RTC
+ * uses 0x51, for just one example.
+ *
+ * Accordingly, explicit board-specific configuration data should be used
+ * in almost all cases. (One partial exception is an SMBus used to access
+ * "SPD" data for DRAM sticks. Those only use 24c02 EEPROMs.)
+ *
+ * So this driver uses "new style" I2C driver binding, expecting to be
+ * told what devices exist. That may be in arch/X/mach-Y/board-Z.c or
+ * similar kernel-resident tables; or, configuration data coming from
+ * a bootloader.
+ *
+ * Other than binding model, current differences from "eeprom" driver are
+ * that this one handles write access and isn't restricted to 24c02 devices.
+ * It also handles larger devices (32 kbit and up) with two-byte addresses,
+ * which won't work on pure SMBus systems.
+ */
+
+struct at24_data {
+       struct at24_platform_data chip;
+       bool use_smbus;
+
+       /*
+        * Lock protects against activities from other Linux tasks,
+        * but not from changes by other I2C masters.
+        */
+       struct mutex lock;
+       struct bin_attribute bin;
+
+       u8 *writebuf;
+       unsigned write_max;
+       unsigned num_addresses;
+
+       /*
+        * Some chips tie up multiple I2C addresses; dummy devices reserve
+        * them for us, and we'll use them with SMBus calls.
+        */
+       struct i2c_client *client[];
+};
+
+/*
+ * This parameter is to help this driver avoid blocking other drivers out
+ * of I2C for potentially troublesome amounts of time. With a 100 kHz I2C
+ * clock, one 256 byte read takes about 1/43 second which is excessive;
+ * but the 1/170 second it takes at 400 kHz may be quite reasonable; and
+ * at 1 MHz (Fm+) a 1/430 second delay could easily be invisible.
+ *
+ * This value is forced to be a power of two so that writes align on pages.
+ */
+static unsigned io_limit = 128;
+module_param(io_limit, uint, 0);
+MODULE_PARM_DESC(io_limit, "Maximum bytes per I/O (default 128)");
+
+/*
+ * Specs often allow 5 msec for a page write, sometimes 20 msec;
+ * it's important to recover from write timeouts.
+ */
+static unsigned write_timeout = 25;
+module_param(write_timeout, uint, 0);
+MODULE_PARM_DESC(write_timeout, "Time (in ms) to try writes (default 25)");
+
+#define AT24_SIZE_BYTELEN 5
+#define AT24_SIZE_FLAGS 8
+
+#define AT24_BITMASK(x) (BIT(x) - 1)
+
+/* create non-zero magic value for given eeprom parameters */
+#define AT24_DEVICE_MAGIC(_len, _flags)                \
+       ((1 << AT24_SIZE_FLAGS | (_flags))              \
+           << AT24_SIZE_BYTELEN | ilog2(_len))
+
+static const struct i2c_device_id at24_ids[] = {
+       /* needs 8 addresses as A0-A2 are ignored */
+       { "24c00", AT24_DEVICE_MAGIC(128 / 8, AT24_FLAG_TAKE8ADDR) },
+       /* old variants can't be handled with this generic entry! */
+       { "24c01", AT24_DEVICE_MAGIC(1024 / 8, 0) },
+       { "24c02", AT24_DEVICE_MAGIC(2048 / 8, 0) },
+       /* spd is a 24c02 in memory DIMMs */
+       { "spd", AT24_DEVICE_MAGIC(2048 / 8,
+               AT24_FLAG_READONLY | AT24_FLAG_IRUGO) },
+       { "24c04", AT24_DEVICE_MAGIC(4096 / 8, 0) },
+       /* 24rf08 quirk is handled at i2c-core */
+       { "24c08", AT24_DEVICE_MAGIC(8192 / 8, 0) },
+       { "24c16", AT24_DEVICE_MAGIC(16384 / 8, 0) },
+       { "24c32", AT24_DEVICE_MAGIC(32768 / 8, AT24_FLAG_ADDR16) },
+       { "24c64", AT24_DEVICE_MAGIC(65536 / 8, AT24_FLAG_ADDR16) },
+       { "24c128", AT24_DEVICE_MAGIC(131072 / 8, AT24_FLAG_ADDR16) },
+       { "24c256", AT24_DEVICE_MAGIC(262144 / 8, AT24_FLAG_ADDR16) },
+       { "24c512", AT24_DEVICE_MAGIC(524288 / 8, AT24_FLAG_ADDR16) },
+       { "24c1024", AT24_DEVICE_MAGIC(1048576 / 8, AT24_FLAG_ADDR16) },
+       { "at24", 0 },
+       { /* END OF LIST */ }
+};
+MODULE_DEVICE_TABLE(i2c, at24_ids);
+
+/*-------------------------------------------------------------------------*/
+
+/*
+ * This routine supports chips which consume multiple I2C addresses. It
+ * computes the addressing information to be used for a given r/w request.
+ * Assumes that sanity checks for offset happened at sysfs-layer.
+ */
+static struct i2c_client *at24_translate_offset(struct at24_data *at24,
+               unsigned *offset)
+{
+       unsigned i;
+
+       if (at24->chip.flags & AT24_FLAG_ADDR16) {
+               i = *offset >> 16;
+               *offset &= 0xffff;
+       } else {
+               i = *offset >> 8;
+               *offset &= 0xff;
+       }
+
+       return at24->client[i];
+}
+
+static ssize_t at24_eeprom_read(struct at24_data *at24, char *buf,
+               unsigned offset, size_t count)
+{
+       struct i2c_msg msg[2];
+       u8 msgbuf[2];
+       struct i2c_client *client;
+       int status, i;
+
+       memset(msg, 0, sizeof(msg));
+
+       /*
+        * REVISIT some multi-address chips don't rollover page reads to
+        * the next slave address, so we may need to truncate the count.
+        * Those chips might need another quirk flag.
+        *
+        * If the real hardware used four adjacent 24c02 chips and that
+        * were misconfigured as one 24c08, that would be a similar effect:
+        * one "eeprom" file not four, but larger reads would fail when
+        * they crossed certain pages.
+        */
+
+       /*
+        * Slave address and byte offset derive from the offset. Always
+        * set the byte address; on a multi-master board, another master
+        * may have changed the chip's "current" address pointer.
+        */
+       client = at24_translate_offset(at24, &offset);
+
+       if (count > io_limit)
+               count = io_limit;
+
+       /* Smaller eeproms can work given some SMBus extension calls */
+       if (at24->use_smbus) {
+               if (count > I2C_SMBUS_BLOCK_MAX)
+                       count = I2C_SMBUS_BLOCK_MAX;
+               status = i2c_smbus_read_i2c_block_data(client, offset,
+                               count, buf);
+               dev_dbg(&client->dev, "smbus read %zd@%d --> %d\n",
+                               count, offset, status);
+               return (status < 0) ? -EIO : status;
+       }
+
+       /*
+        * When we have a better choice than SMBus calls, use a combined
+        * I2C message. Write address; then read up to io_limit data bytes.
+        * Note that read page rollover helps us here (unlike writes).
+        * msgbuf is u8 and will cast to our needs.
+        */
+       i = 0;
+       if (at24->chip.flags & AT24_FLAG_ADDR16)
+               msgbuf[i++] = offset >> 8;
+       msgbuf[i++] = offset;
+
+       msg[0].addr = client->addr;
+       msg[0].buf = msgbuf;
+       msg[0].len = i;
+
+       msg[1].addr = client->addr;
+       msg[1].flags = I2C_M_RD;
+       msg[1].buf = buf;
+       msg[1].len = count;
+
+       status = i2c_transfer(client->adapter, msg, 2);
+       dev_dbg(&client->dev, "i2c read %zd@%d --> %d\n",
+                       count, offset, status);
+
+       if (status == 2)
+               return count;
+       else if (status >= 0)
+               return -EIO;
+       else
+               return status;
+}
+
+static ssize_t at24_bin_read(struct kobject *kobj, struct bin_attribute *attr,
+               char *buf, loff_t off, size_t count)
+{
+       struct at24_data *at24;
+       ssize_t retval = 0;
+
+       at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+       if (unlikely(!count))
+               return count;
+
+       /*
+        * Read data from chip, protecting against concurrent updates
+        * from this host, but not from other I2C masters.
+        */
+       mutex_lock(&at24->lock);
+
+       while (count) {
+               ssize_t status;
+
+               status = at24_eeprom_read(at24, buf, off, count);
+               if (status <= 0) {
+                       if (retval == 0)
+                               retval = status;
+                       break;
+               }
+               buf += status;
+               off += status;
+               count -= status;
+               retval += status;
+       }
+
+       mutex_unlock(&at24->lock);
+
+       return retval;
+}
+
+
+/*
+ * REVISIT: export at24_bin{read,write}() to let other kernel code use
+ * eeprom data. For example, it might hold a board's Ethernet address, or
+ * board-specific calibration data generated on the manufacturing floor.
+ */
+
+
+/*
+ * Note that if the hardware write-protect pin is pulled high, the whole
+ * chip is normally write protected. But there are plenty of product
+ * variants here, including OTP fuses and partial chip protect.
+ *
+ * We only use page mode writes; the alternative is sloooow. This routine
+ * writes at most one page.
+ */
+static ssize_t at24_eeprom_write(struct at24_data *at24, char *buf,
+               unsigned offset, size_t count)
+{
+       struct i2c_client *client;
+       struct i2c_msg msg;
+       ssize_t status;
+       unsigned long timeout, write_time;
+       unsigned next_page;
+
+       /* Get corresponding I2C address and adjust offset */
+       client = at24_translate_offset(at24, &offset);
+
+       /* write_max is at most a page */
+       if (count > at24->write_max)
+               count = at24->write_max;
+
+       /* Never roll over backwards, to the start of this page */
+       next_page = roundup(offset + 1, at24->chip.page_size);
+       if (offset + count > next_page)
+               count = next_page - offset;
+
+       /* If we'll use I2C calls for I/O, set up the message */
+       if (!at24->use_smbus) {
+               int i = 0;
+
+               msg.addr = client->addr;
+               msg.flags = 0;
+
+               /* msg.buf is u8 and casts will mask the values */
+               msg.buf = at24->writebuf;
+               if (at24->chip.flags & AT24_FLAG_ADDR16)
+                       msg.buf[i++] = offset >> 8;
+
+               msg.buf[i++] = offset;
+               memcpy(&msg.buf[i], buf, count);
+               msg.len = i + count;
+       }
+
+       /*
+        * Writes fail if the previous one didn't complete yet. We may
+        * loop a few times until this one succeeds, waiting at least
+        * long enough for one entire page write to work.
+        */
+       timeout = jiffies + msecs_to_jiffies(write_timeout);
+       do {
+               write_time = jiffies;
+               if (at24->use_smbus) {
+                       status = i2c_smbus_write_i2c_block_data(client,
+                                       offset, count, buf);
+                       if (status == 0)
+                               status = count;
+               } else {
+                       status = i2c_transfer(client->adapter, &msg, 1);
+                       if (status == 1)
+                               status = count;
+               }
+               dev_dbg(&client->dev, "write %zd@%d --> %zd (%ld)\n",
+                               count, offset, status, jiffies);
+
+               if (status == count)
+                       return count;
+
+               /* REVISIT: at HZ=100, this is sloooow */
+               msleep(1);
+       } while (time_before(write_time, timeout));
+
+       return -ETIMEDOUT;
+}
+
+static ssize_t at24_bin_write(struct kobject *kobj, struct bin_attribute *attr,
+               char *buf, loff_t off, size_t count)
+{
+       struct at24_data *at24;
+       ssize_t retval = 0;
+
+       at24 = dev_get_drvdata(container_of(kobj, struct device, kobj));
+
+       if (unlikely(!count))
+               return count;
+
+       /*
+        * Write data to chip, protecting against concurrent updates
+        * from this host, but not from other I2C masters.
+        */
+       mutex_lock(&at24->lock);
+
+       while (count) {
+               ssize_t status;
+
+               status = at24_eeprom_write(at24, buf, off, count);
+               if (status <= 0) {
+                       if (retval == 0)
+                               retval = status;
+                       break;
+               }
+               buf += status;
+               off += status;
+               count -= status;
+               retval += status;
+       }
+
+       mutex_unlock(&at24->lock);
+
+       return retval;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static int at24_probe(struct i2c_client *client, const struct i2c_device_id *id)
+{
+       struct at24_platform_data chip;
+       bool writable;
+       bool use_smbus = false;
+       struct at24_data *at24;
+       int err;
+       unsigned i, num_addresses;
+       kernel_ulong_t magic;
+
+       if (client->dev.platform_data) {
+               chip = *(struct at24_platform_data *)client->dev.platform_data;
+       } else {
+               if (!id->driver_data) {
+                       err = -ENODEV;
+                       goto err_out;
+               }
+               magic = id->driver_data;
+               chip.byte_len = BIT(magic & AT24_BITMASK(AT24_SIZE_BYTELEN));
+               magic >>= AT24_SIZE_BYTELEN;
+               chip.flags = magic & AT24_BITMASK(AT24_SIZE_FLAGS);
+               /*
+                * This is slow, but we can't know all eeproms, so we better
+                * play safe. Specifying custom eeprom-types via platform_data
+                * is recommended anyhow.
+                */
+               chip.page_size = 1;
+       }
+
+       if (!is_power_of_2(chip.byte_len))
+               dev_warn(&client->dev,
+                       "byte_len looks suspicious (no power of 2)!\n");
+       if (!is_power_of_2(chip.page_size))
+               dev_warn(&client->dev,
+                       "page_size looks suspicious (no power of 2)!\n");
+
+       /* Use I2C operations unless we're stuck with SMBus extensions. */
+       if (!i2c_check_functionality(client->adapter, I2C_FUNC_I2C)) {
+               if (chip.flags & AT24_FLAG_ADDR16) {
+                       err = -EPFNOSUPPORT;
+                       goto err_out;
+               }
+               if (!i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_READ_I2C_BLOCK)) {
+                       err = -EPFNOSUPPORT;
+                       goto err_out;
+               }
+               use_smbus = true;
+       }
+
+       if (chip.flags & AT24_FLAG_TAKE8ADDR)
+               num_addresses = 8;
+       else
+               num_addresses = DIV_ROUND_UP(chip.byte_len,
+                       (chip.flags & AT24_FLAG_ADDR16) ? 65536 : 256);
+
+       at24 = kzalloc(sizeof(struct at24_data) +
+               num_addresses * sizeof(struct i2c_client *), GFP_KERNEL);
+       if (!at24) {
+               err = -ENOMEM;
+               goto err_out;
+       }
+
+       mutex_init(&at24->lock);
+       at24->use_smbus = use_smbus;
+       at24->chip = chip;
+       at24->num_addresses = num_addresses;
+
+       /*
+        * Export the EEPROM bytes through sysfs, since that's convenient.
+        * By default, only root should see the data (maybe passwords etc)
+        */
+       at24->bin.attr.name = "eeprom";
+       at24->bin.attr.mode = chip.flags & AT24_FLAG_IRUGO ? S_IRUGO : S_IRUSR;
+       at24->bin.attr.owner = THIS_MODULE;
+       at24->bin.read = at24_bin_read;
+       at24->bin.size = chip.byte_len;
+
+       writable = !(chip.flags & AT24_FLAG_READONLY);
+       if (writable) {
+               if (!use_smbus || i2c_check_functionality(client->adapter,
+                               I2C_FUNC_SMBUS_WRITE_I2C_BLOCK)) {
+
+                       unsigned write_max = chip.page_size;
+
+                       at24->bin.write = at24_bin_write;
+                       at24->bin.attr.mode |= S_IWUSR;
+
+                       if (write_max > io_limit)
+                               write_max = io_limit;
+                       if (use_smbus && write_max > I2C_SMBUS_BLOCK_MAX)
+                               write_max = I2C_SMBUS_BLOCK_MAX;
+                       at24->write_max = write_max;
+
+                       /* buffer (data + address at the beginning) */
+                       at24->writebuf = kmalloc(write_max + 2, GFP_KERNEL);
+                       if (!at24->writebuf) {
+                               err = -ENOMEM;
+                               goto err_struct;
+                       }
+               } else {
+                       dev_warn(&client->dev,
+                               "cannot write due to controller restrictions.");
+               }
+       }
+
+       at24->client[0] = client;
+
+       /* use dummy devices for multiple-address chips */
+       for (i = 1; i < num_addresses; i++) {
+               at24->client[i] = i2c_new_dummy(client->adapter,
+                                       client->addr + i);
+               if (!at24->client[i]) {
+                       dev_err(&client->dev, "address 0x%02x unavailable\n",
+                                       client->addr + i);
+                       err = -EADDRINUSE;
+                       goto err_clients;
+               }
+       }
+
+       err = sysfs_create_bin_file(&client->dev.kobj, &at24->bin);
+       if (err)
+               goto err_clients;
+
+       i2c_set_clientdata(client, at24);
+
+       dev_info(&client->dev, "%Zd byte %s EEPROM %s\n",
+               at24->bin.size, client->name,
+               writable ? "(writable)" : "(read-only)");
+       dev_dbg(&client->dev,
+               "page_size %d, num_addresses %d, write_max %d%s\n",
+               chip.page_size, num_addresses,
+               at24->write_max,
+               use_smbus ? ", use_smbus" : "");
+
+       return 0;
+
+err_clients:
+       for (i = 1; i < num_addresses; i++)
+               if (at24->client[i])
+                       i2c_unregister_device(at24->client[i]);
+
+       kfree(at24->writebuf);
+err_struct:
+       kfree(at24);
+err_out:
+       dev_dbg(&client->dev, "probe error %d\n", err);
+       return err;
+}
+
+static int __devexit at24_remove(struct i2c_client *client)
+{
+       struct at24_data *at24;
+       int i;
+
+       at24 = i2c_get_clientdata(client);
+       sysfs_remove_bin_file(&client->dev.kobj, &at24->bin);
+
+       for (i = 1; i < at24->num_addresses; i++)
+               i2c_unregister_device(at24->client[i]);
+
+       kfree(at24->writebuf);
+       kfree(at24);
+       i2c_set_clientdata(client, NULL);
+       return 0;
+}
+
+/*-------------------------------------------------------------------------*/
+
+static struct i2c_driver at24_driver = {
+       .driver = {
+               .name = "at24",
+               .owner = THIS_MODULE,
+       },
+       .probe = at24_probe,
+       .remove = __devexit_p(at24_remove),
+       .id_table = at24_ids,
+};
+
+static int __init at24_init(void)
+{
+       io_limit = rounddown_pow_of_two(io_limit);
+       return i2c_add_driver(&at24_driver);
+}
+module_init(at24_init);
+
+static void __exit at24_exit(void)
+{
+       i2c_del_driver(&at24_driver);
+}
+module_exit(at24_exit);
+
+MODULE_DESCRIPTION("Driver for most I2C EEPROMs");
+MODULE_AUTHOR("David Brownell and Wolfram Sang");
+MODULE_LICENSE("GPL");
index 7dee001e5133bc7df391bc187e28ae082b9315d2..373ea8d8fe8f0dd7af8c2cbe343c41a48741f2d3 100644 (file)
@@ -1,15 +1,9 @@
 /*
-    eeprom.c - Part of lm_sensors, Linux kernel modules for hardware
-               monitoring
     Copyright (C) 1998, 1999  Frodo Looijaard <frodol@dds.nl> and
                               Philip Edelbrock <phil@netroedge.com>
     Copyright (C) 2003 Greg Kroah-Hartman <greg@kroah.com>
     Copyright (C) 2003 IBM Corp.
-
-    2004-01-16  Jean Delvare <khali@linux-fr.org>
-    Divide the eeprom in 32-byte (arbitrary) slices. This significantly
-    speeds sensors up, as well as various scripts using the eeprom
-    module.
+    Copyright (C) 2004 Jean Delvare <khali@linux-fr.org>
 
     This program is free software; you can redistribute it and/or modify
     it under the terms of the GNU General Public License as published by
@@ -78,7 +72,7 @@ static struct i2c_driver eeprom_driver = {
 static void eeprom_update_client(struct i2c_client *client, u8 slice)
 {
        struct eeprom_data *data = i2c_get_clientdata(client);
-       int i, j;
+       int i;
 
        mutex_lock(&data->update_lock);
 
@@ -93,15 +87,12 @@ static void eeprom_update_client(struct i2c_client *client, u8 slice)
                                                        != 32)
                                        goto exit;
                } else {
-                       if (i2c_smbus_write_byte(client, slice << 5)) {
-                               dev_dbg(&client->dev, "eeprom read start has failed!\n");
-                               goto exit;
-                       }
-                       for (i = slice << 5; i < (slice + 1) << 5; i++) {
-                               j = i2c_smbus_read_byte(client);
-                               if (j < 0)
+                       for (i = slice << 5; i < (slice + 1) << 5; i += 2) {
+                               int word = i2c_smbus_read_word_data(client, i);
+                               if (word < 0)
                                        goto exit;
-                               data->data[i] = (u8) j;
+                               data->data[i] = word & 0xff;
+                               data->data[i + 1] = word >> 8;
                        }
                }
                data->last_updated[slice] = jiffies;
@@ -159,24 +150,33 @@ static struct bin_attribute eeprom_attr = {
 
 static int eeprom_attach_adapter(struct i2c_adapter *adapter)
 {
+       if (!(adapter->class & (I2C_CLASS_DDC | I2C_CLASS_SPD)))
+               return 0;
        return i2c_probe(adapter, &addr_data, eeprom_detect);
 }
 
 /* This function is called by i2c_probe */
 static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-       struct i2c_client *new_client;
+       struct i2c_client *client;
        struct eeprom_data *data;
        int err = 0;
 
-       /* There are three ways we can read the EEPROM data:
+       /* EDID EEPROMs are often 24C00 EEPROMs, which answer to all
+          addresses 0x50-0x57, but we only care about 0x50. So decline
+          attaching to addresses >= 0x51 on DDC buses */
+       if (!(adapter->class & I2C_CLASS_SPD) && address >= 0x51)
+               goto exit;
+
+       /* There are four ways we can read the EEPROM data:
           (1) I2C block reads (faster, but unsupported by most adapters)
-          (2) Consecutive byte reads (100% overhead)
-          (3) Regular byte data reads (200% overhead)
-          The third method is not implemented by this driver because all
-          known adapters support at least the second. */
-       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA
-                                           | I2C_FUNC_SMBUS_BYTE))
+          (2) Word reads (128% overhead)
+          (3) Consecutive byte reads (88% overhead, unsafe)
+          (4) Regular byte data reads (265% overhead)
+          The third and fourth methods are not implemented by this driver
+          because all known adapters support one of the first two. */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_WORD_DATA)
+        && !i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_I2C_BLOCK))
                goto exit;
 
        if (!(data = kzalloc(sizeof(struct eeprom_data), GFP_KERNEL))) {
@@ -184,50 +184,49 @@ static int eeprom_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit;
        }
 
-       new_client = &data->client;
+       client = &data->client;
        memset(data->data, 0xff, EEPROM_SIZE);
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
-       new_client->adapter = adapter;
-       new_client->driver = &eeprom_driver;
-       new_client->flags = 0;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &eeprom_driver;
 
        /* Fill in the remaining client fields */
-       strlcpy(new_client->name, "eeprom", I2C_NAME_SIZE);
-       data->valid = 0;
+       strlcpy(client->name, "eeprom", I2C_NAME_SIZE);
        mutex_init(&data->update_lock);
        data->nature = UNKNOWN;
 
        /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(new_client)))
+       if ((err = i2c_attach_client(client)))
                goto exit_kfree;
 
        /* Detect the Vaio nature of EEPROMs.
           We use the "PCG-" or "VGN-" prefix as the signature. */
-       if (address == 0x57) {
+       if (address == 0x57
+        && i2c_check_functionality(adapter, I2C_FUNC_SMBUS_READ_BYTE_DATA)) {
                char name[4];
 
-               name[0] = i2c_smbus_read_byte_data(new_client, 0x80);
-               name[1] = i2c_smbus_read_byte(new_client);
-               name[2] = i2c_smbus_read_byte(new_client);
-               name[3] = i2c_smbus_read_byte(new_client);
+               name[0] = i2c_smbus_read_byte_data(client, 0x80);
+               name[1] = i2c_smbus_read_byte_data(client, 0x81);
+               name[2] = i2c_smbus_read_byte_data(client, 0x82);
+               name[3] = i2c_smbus_read_byte_data(client, 0x83);
 
                if (!memcmp(name, "PCG-", 4) || !memcmp(name, "VGN-", 4)) {
-                       dev_info(&new_client->dev, "Vaio EEPROM detected, "
+                       dev_info(&client->dev, "Vaio EEPROM detected, "
                                 "enabling privacy protection\n");
                        data->nature = VAIO;
                }
        }
 
        /* create the sysfs eeprom file */
-       err = sysfs_create_bin_file(&new_client->dev.kobj, &eeprom_attr);
+       err = sysfs_create_bin_file(&client->dev.kobj, &eeprom_attr);
        if (err)
                goto exit_detach;
 
        return 0;
 
 exit_detach:
-       i2c_detach_client(new_client);
+       i2c_detach_client(client);
 exit_kfree:
        kfree(data);
 exit:
index cf507b3f60f3567888bc4c964767744652bec99d..5a0285d8b6f9888f9477d4a1a7284f0dd5a7bee6 100644 (file)
@@ -170,7 +170,7 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
        struct i2c_client *real_client;
        struct i2c_client *fake_client;
        struct max6875_data *data;
-       int err = 0;
+       int err;
 
        if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_WRITE_BYTE_DATA
                                     | I2C_FUNC_SMBUS_READ_BYTE))
@@ -195,7 +195,6 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
        real_client->addr = address;
        real_client->adapter = adapter;
        real_client->driver = &max6875_driver;
-       real_client->flags = 0;
        strlcpy(real_client->name, "max6875", I2C_NAME_SIZE);
        mutex_init(&data->update_lock);
 
@@ -204,7 +203,6 @@ static int max6875_detect(struct i2c_adapter *adapter, int address, int kind)
        fake_client->addr = address | 1;
        fake_client->adapter = adapter;
        fake_client->driver = &max6875_driver;
-       fake_client->flags = 0;
        strlcpy(fake_client->name, "max6875 subclient", I2C_NAME_SIZE);
 
        if ((err = i2c_attach_client(real_client)) != 0)
index f43c4e79b55e9b3cf9bf0bba1317a0196aadddea..58ab7f26be26d1327f17c10a709e2c5ccd3da74f 100644 (file)
@@ -113,7 +113,7 @@ static int pca9539_attach_adapter(struct i2c_adapter *adapter)
 /* This function is called by i2c_probe */
 static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-       struct i2c_client *new_client;
+       struct i2c_client *client;
        struct pca9539_data *data;
        int err = 0;
 
@@ -127,29 +127,28 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit;
        }
 
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
-       new_client->adapter = adapter;
-       new_client->driver = &pca9539_driver;
-       new_client->flags = 0;
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &pca9539_driver;
 
        if (kind < 0) {
                /* Detection: the pca9539 only has 8 registers (0-7).
                   A read of 7 should succeed, but a read of 8 should fail. */
-               if ((i2c_smbus_read_byte_data(new_client, 7) < 0) ||
-                   (i2c_smbus_read_byte_data(new_client, 8) >= 0))
+               if ((i2c_smbus_read_byte_data(client, 7) < 0) ||
+                   (i2c_smbus_read_byte_data(client, 8) >= 0))
                        goto exit_kfree;
        }
 
-       strlcpy(new_client->name, "pca9539", I2C_NAME_SIZE);
+       strlcpy(client->name, "pca9539", I2C_NAME_SIZE);
 
        /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(new_client)))
+       if ((err = i2c_attach_client(client)))
                goto exit_kfree;
 
        /* Register sysfs hooks */
-       err = sysfs_create_group(&new_client->dev.kobj,
+       err = sysfs_create_group(&client->dev.kobj,
                                 &pca9539_defattr_group);
        if (err)
                goto exit_detach;
@@ -157,7 +156,7 @@ static int pca9539_detect(struct i2c_adapter *adapter, int address, int kind)
        return 0;
 
 exit_detach:
-       i2c_detach_client(new_client);
+       i2c_detach_client(client);
 exit_kfree:
        kfree(data);
 exit:
index e5b31329b56e146e1022be115c0d7e0cbdc88ede..1b3db2b3ada9506d2a108f499753ba933d33be00 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    pcf8574.c - Part of lm_sensors, Linux kernel modules for hardware
-             monitoring
     Copyright (c) 2000  Frodo Looijaard <frodol@dds.nl>, 
                         Philip Edelbrock <phil@netroedge.com>,
                         Dan Eaton <dan.eaton@rocketlogix.com>
@@ -129,7 +127,7 @@ static int pcf8574_attach_adapter(struct i2c_adapter *adapter)
 /* This function is called by i2c_probe */
 static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-       struct i2c_client *new_client;
+       struct i2c_client *client;
        struct pcf8574_data *data;
        int err = 0;
        const char *client_name = "";
@@ -144,12 +142,11 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit;
        }
 
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
-       new_client->adapter = adapter;
-       new_client->driver = &pcf8574_driver;
-       new_client->flags = 0;
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &pcf8574_driver;
 
        /* Now, we would do the remaining detection. But the PCF8574 is plainly
           impossible to detect! Stupid chip. */
@@ -168,23 +165,23 @@ static int pcf8574_detect(struct i2c_adapter *adapter, int address, int kind)
                client_name = "pcf8574";
 
        /* Fill in the remaining client fields and put it into the global list */
-       strlcpy(new_client->name, client_name, I2C_NAME_SIZE);
+       strlcpy(client->name, client_name, I2C_NAME_SIZE);
 
        /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(new_client)))
+       if ((err = i2c_attach_client(client)))
                goto exit_free;
        
        /* Initialize the PCF8574 chip */
-       pcf8574_init_client(new_client);
+       pcf8574_init_client(client);
 
        /* Register sysfs hooks */
-       err = sysfs_create_group(&new_client->dev.kobj, &pcf8574_attr_group);
+       err = sysfs_create_group(&client->dev.kobj, &pcf8574_attr_group);
        if (err)
                goto exit_detach;
        return 0;
 
       exit_detach:
-       i2c_detach_client(new_client);
+       i2c_detach_client(client);
       exit_free:
        kfree(data);
       exit:
index 66c7c3bb9429754bbe7f6c31737feefdda750fa0..db735379f22fe512dfdc58402f8891d02bfbca69 100644 (file)
@@ -1,6 +1,4 @@
 /*
-    pcf8591.c - Part of lm_sensors, Linux kernel modules for hardware
-                monitoring
     Copyright (C) 2001-2004 Aurelien Jarno <aurelien@aurel32.net>
     Ported to Linux 2.6 by Aurelien Jarno <aurelien@aurel32.net> with 
     the help of Jean Delvare <khali@linux-fr.org>
@@ -190,7 +188,7 @@ static int pcf8591_attach_adapter(struct i2c_adapter *adapter)
 /* This function is called by i2c_probe */
 static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
 {
-       struct i2c_client *new_client;
+       struct i2c_client *client;
        struct pcf8591_data *data;
        int err = 0;
 
@@ -205,12 +203,11 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
                goto exit;
        }
        
-       new_client = &data->client;
-       i2c_set_clientdata(new_client, data);
-       new_client->addr = address;
-       new_client->adapter = adapter;
-       new_client->driver = &pcf8591_driver;
-       new_client->flags = 0;
+       client = &data->client;
+       i2c_set_clientdata(client, data);
+       client->addr = address;
+       client->adapter = adapter;
+       client->driver = &pcf8591_driver;
 
        /* Now, we would do the remaining detection. But the PCF8591 is plainly
           impossible to detect! Stupid chip. */
@@ -221,31 +218,31 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
 
        /* Fill in the remaining client fields and put it into the global 
           list */
-       strlcpy(new_client->name, "pcf8591", I2C_NAME_SIZE);
+       strlcpy(client->name, "pcf8591", I2C_NAME_SIZE);
        mutex_init(&data->update_lock);
 
        /* Tell the I2C layer a new client has arrived */
-       if ((err = i2c_attach_client(new_client)))
+       if ((err = i2c_attach_client(client)))
                goto exit_kfree;
 
        /* Initialize the PCF8591 chip */
-       pcf8591_init_client(new_client);
+       pcf8591_init_client(client);
 
        /* Register sysfs hooks */
-       err = sysfs_create_group(&new_client->dev.kobj, &pcf8591_attr_group);
+       err = sysfs_create_group(&client->dev.kobj, &pcf8591_attr_group);
        if (err)
                goto exit_detach;
 
        /* Register input2 if not in "two differential inputs" mode */
        if (input_mode != 3) {
-               if ((err = device_create_file(&new_client->dev,
+               if ((err = device_create_file(&client->dev,
                                              &dev_attr_in2_input)))
                        goto exit_sysfs_remove;
        }
 
        /* Register input3 only in "four single ended inputs" mode */
        if (input_mode == 0) {
-               if ((err = device_create_file(&new_client->dev,
+               if ((err = device_create_file(&client->dev,
                                              &dev_attr_in3_input)))
                        goto exit_sysfs_remove;
        }
@@ -253,10 +250,10 @@ static int pcf8591_detect(struct i2c_adapter *adapter, int address, int kind)
        return 0;
 
 exit_sysfs_remove:
-       sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group_opt);
-       sysfs_remove_group(&new_client->dev.kobj, &pcf8591_attr_group);
+       sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group_opt);
+       sysfs_remove_group(&client->dev.kobj, &pcf8591_attr_group);
 exit_detach:
-       i2c_detach_client(new_client);
+       i2c_detach_client(client);
 exit_kfree:
        kfree(data);
 exit:
index d0175f4f8fc683941057bf4866e97a8a9abdcfd3..0a79f7661017b0a548868db95bba17e2d73a2796 100644 (file)
 #include <linux/i2c.h>
 #include <linux/init.h>
 #include <linux/idr.h>
-#include <linux/seq_file.h>
 #include <linux/platform_device.h>
 #include <linux/mutex.h>
 #include <linux/completion.h>
 #include <linux/hardirq.h>
 #include <linux/irqflags.h>
-#include <linux/semaphore.h>
 #include <asm/uaccess.h>
 
 #include "i2c-core.h"
@@ -44,7 +42,9 @@
 static DEFINE_MUTEX(core_lock);
 static DEFINE_IDR(i2c_adapter_idr);
 
-#define is_newstyle_driver(d) ((d)->probe || (d)->remove)
+#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect)
+
+static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver);
 
 /* ------------------------------------------------------------------------- */
 
@@ -103,19 +103,14 @@ static int i2c_device_probe(struct device *dev)
 {
        struct i2c_client       *client = to_i2c_client(dev);
        struct i2c_driver       *driver = to_i2c_driver(dev->driver);
-       const struct i2c_device_id *id;
        int status;
 
-       if (!driver->probe)
+       if (!driver->probe || !driver->id_table)
                return -ENODEV;
        client->driver = driver;
        dev_dbg(dev, "probe\n");
 
-       if (driver->id_table)
-               id = i2c_match_id(driver->id_table, client);
-       else
-               id = NULL;
-       status = driver->probe(client, id);
+       status = driver->probe(client, i2c_match_id(driver->id_table, client));
        if (status)
                client->driver = NULL;
        return status;
@@ -208,7 +203,7 @@ static struct device_attribute i2c_dev_attrs[] = {
        { },
 };
 
-static struct bus_type i2c_bus_type = {
+struct bus_type i2c_bus_type = {
        .name           = "i2c",
        .dev_attrs      = i2c_dev_attrs,
        .match          = i2c_device_match,
@@ -219,6 +214,7 @@ static struct bus_type i2c_bus_type = {
        .suspend        = i2c_device_suspend,
        .resume         = i2c_device_resume,
 };
+EXPORT_SYMBOL_GPL(i2c_bus_type);
 
 
 /**
@@ -306,6 +302,14 @@ void i2c_unregister_device(struct i2c_client *client)
                return;
        }
 
+       if (adapter->client_unregister) {
+               if (adapter->client_unregister(client)) {
+                       dev_warn(&client->dev,
+                                "client_unregister [%s] failed\n",
+                                client->name);
+               }
+       }
+
        mutex_lock(&adapter->clist_lock);
        list_del(&client->list);
        mutex_unlock(&adapter->clist_lock);
@@ -416,6 +420,10 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data)
        struct i2c_driver *driver = to_i2c_driver(d);
        struct i2c_adapter *adap = data;
 
+       /* Detect supported devices on that bus, and instantiate them */
+       i2c_detect(adap, driver);
+
+       /* Let legacy drivers scan this bus for matching devices */
        if (driver->attach_adapter) {
                /* We ignore the return code; if it fails, too bad */
                driver->attach_adapter(adap);
@@ -455,7 +463,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
        if (adap->nr < __i2c_first_dynamic_bus_num)
                i2c_scan_static_board_info(adap);
 
-       /* let legacy drivers scan this bus for matching devices */
+       /* Notify drivers */
        dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
                                 i2c_do_add_adapter);
 
@@ -561,8 +569,19 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
 {
        struct i2c_driver *driver = to_i2c_driver(d);
        struct i2c_adapter *adapter = data;
+       struct i2c_client *client, *_n;
        int res;
 
+       /* Remove the devices we created ourselves */
+       list_for_each_entry_safe(client, _n, &driver->clients, detected) {
+               if (client->adapter == adapter) {
+                       dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
+                               client->name, client->addr);
+                       list_del(&client->detected);
+                       i2c_unregister_device(client);
+               }
+       }
+
        if (!driver->detach_adapter)
                return 0;
        res = driver->detach_adapter(adapter);
@@ -582,8 +601,7 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data)
  */
 int i2c_del_adapter(struct i2c_adapter *adap)
 {
-       struct list_head  *item, *_n;
-       struct i2c_client *client;
+       struct i2c_client *client, *_n;
        int res = 0;
 
        mutex_lock(&core_lock);
@@ -604,10 +622,9 @@ int i2c_del_adapter(struct i2c_adapter *adap)
 
        /* detach any active clients. This must be done first, because
         * it can fail; in which case we give up. */
-       list_for_each_safe(item, _n, &adap->clients) {
+       list_for_each_entry_safe(client, _n, &adap->clients, list) {
                struct i2c_driver       *driver;
 
-               client = list_entry(item, struct i2c_client, list);
                driver = client->driver;
 
                /* new style, follow standard driver model */
@@ -646,6 +663,20 @@ EXPORT_SYMBOL(i2c_del_adapter);
 
 /* ------------------------------------------------------------------------- */
 
+static int __attach_adapter(struct device *dev, void *data)
+{
+       struct i2c_adapter *adapter = to_i2c_adapter(dev);
+       struct i2c_driver *driver = data;
+
+       i2c_detect(adapter, driver);
+
+       /* Legacy drivers scan i2c busses directly */
+       if (driver->attach_adapter)
+               driver->attach_adapter(adapter);
+
+       return 0;
+}
+
 /*
  * An i2c_driver is used with one or more i2c_client (device) nodes to access
  * i2c slave chips, on a bus instance associated with some i2c_adapter.  There
@@ -685,72 +716,70 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
 
        pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name);
 
-       /* legacy drivers scan i2c busses directly */
-       if (driver->attach_adapter) {
-               struct i2c_adapter *adapter;
-
-               down(&i2c_adapter_class.sem);
-               list_for_each_entry(adapter, &i2c_adapter_class.devices,
-                                   dev.node) {
-                       driver->attach_adapter(adapter);
-               }
-               up(&i2c_adapter_class.sem);
-       }
+       INIT_LIST_HEAD(&driver->clients);
+       /* Walk the adapters that are already present */
+       class_for_each_device(&i2c_adapter_class, driver, __attach_adapter);
 
        mutex_unlock(&core_lock);
        return 0;
 }
 EXPORT_SYMBOL(i2c_register_driver);
 
-/**
- * i2c_del_driver - unregister I2C driver
- * @driver: the driver being unregistered
- * Context: can sleep
- */
-void i2c_del_driver(struct i2c_driver *driver)
+static int __detach_adapter(struct device *dev, void *data)
 {
-       struct list_head   *item2, *_n;
-       struct i2c_client  *client;
-       struct i2c_adapter *adap;
+       struct i2c_adapter *adapter = to_i2c_adapter(dev);
+       struct i2c_driver *driver = data;
+       struct i2c_client *client, *_n;
 
-       mutex_lock(&core_lock);
+       list_for_each_entry_safe(client, _n, &driver->clients, detected) {
+               dev_dbg(&adapter->dev, "Removing %s at 0x%x\n",
+                       client->name, client->addr);
+               list_del(&client->detected);
+               i2c_unregister_device(client);
+       }
 
-       /* new-style driver? */
        if (is_newstyle_driver(driver))
-               goto unregister;
+               return 0;
 
        /* Have a look at each adapter, if clients of this driver are still
         * attached. If so, detach them to be able to kill the driver
         * afterwards.
         */
-       down(&i2c_adapter_class.sem);
-       list_for_each_entry(adap, &i2c_adapter_class.devices, dev.node) {
-               if (driver->detach_adapter) {
-                       if (driver->detach_adapter(adap)) {
-                               dev_err(&adap->dev, "detach_adapter failed "
-                                       "for driver [%s]\n",
-                                       driver->driver.name);
-                       }
-               } else {
-                       list_for_each_safe(item2, _n, &adap->clients) {
-                               client = list_entry(item2, struct i2c_client, list);
-                               if (client->driver != driver)
-                                       continue;
-                               dev_dbg(&adap->dev, "detaching client [%s] "
-                                       "at 0x%02x\n", client->name,
-                                       client->addr);
-                               if (driver->detach_client(client)) {
-                                       dev_err(&adap->dev, "detach_client "
-                                               "failed for client [%s] at "
-                                               "0x%02x\n", client->name,
-                                               client->addr);
-                               }
-                       }
+       if (driver->detach_adapter) {
+               if (driver->detach_adapter(adapter))
+                       dev_err(&adapter->dev,
+                               "detach_adapter failed for driver [%s]\n",
+                               driver->driver.name);
+       } else {
+               struct i2c_client *client, *_n;
+
+               list_for_each_entry_safe(client, _n, &adapter->clients, list) {
+                       if (client->driver != driver)
+                               continue;
+                       dev_dbg(&adapter->dev,
+                               "detaching client [%s] at 0x%02x\n",
+                               client->name, client->addr);
+                       if (driver->detach_client(client))
+                               dev_err(&adapter->dev, "detach_client "
+                                       "failed for client [%s] at 0x%02x\n",
+                                       client->name, client->addr);
                }
        }
-       up(&i2c_adapter_class.sem);
 
- unregister:
+       return 0;
+}
+
+/**
+ * i2c_del_driver - unregister I2C driver
+ * @driver: the driver being unregistered
+ * Context: can sleep
+ */
+void i2c_del_driver(struct i2c_driver *driver)
+{
+       mutex_lock(&core_lock);
+
+       class_for_each_device(&i2c_adapter_class, driver, __detach_adapter);
+
        driver_unregister(&driver->driver);
        pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name);
 
@@ -863,8 +892,9 @@ EXPORT_SYMBOL(i2c_detach_client);
  */
 struct i2c_client *i2c_use_client(struct i2c_client *client)
 {
-       get_device(&client->dev);
-       return client;
+       if (client && get_device(&client->dev))
+               return client;
+       return NULL;
 }
 EXPORT_SYMBOL(i2c_use_client);
 
@@ -876,7 +906,8 @@ EXPORT_SYMBOL(i2c_use_client);
  */
 void i2c_release_client(struct i2c_client *client)
 {
-       put_device(&client->dev);
+       if (client)
+               put_device(&client->dev);
 }
 EXPORT_SYMBOL(i2c_release_client);
 
@@ -942,10 +973,39 @@ module_exit(i2c_exit);
  * ----------------------------------------------------
  */
 
+/**
+ * i2c_transfer - execute a single or combined I2C message
+ * @adap: Handle to I2C bus
+ * @msgs: One or more messages to execute before STOP is issued to
+ *     terminate the operation; each message begins with a START.
+ * @num: Number of messages to be executed.
+ *
+ * Returns negative errno, else the number of messages executed.
+ *
+ * Note that there is no requirement that each message be sent to
+ * the same slave address, although that is the most common model.
+ */
 int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
 {
        int ret;
 
+       /* REVISIT the fault reporting model here is weak:
+        *
+        *  - When we get an error after receiving N bytes from a slave,
+        *    there is no way to report "N".
+        *
+        *  - When we get a NAK after transmitting N bytes to a slave,
+        *    there is no way to report "N" ... or to let the master
+        *    continue executing the rest of this combined message, if
+        *    that's the appropriate response.
+        *
+        *  - When for example "num" is two and we successfully complete
+        *    the first message but get an error part way through the
+        *    second, it's unclear whether that should be reported as
+        *    one (discarding status on the second message) or errno
+        *    (discarding status on the first one).
+        */
+
        if (adap->algo->master_xfer) {
 #ifdef DEBUG
                for (ret = 0; ret < num; ret++) {
@@ -971,11 +1031,19 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num)
                return ret;
        } else {
                dev_dbg(&adap->dev, "I2C level transfers not supported\n");
-               return -ENOSYS;
+               return -EOPNOTSUPP;
        }
 }
 EXPORT_SYMBOL(i2c_transfer);
 
+/**
+ * i2c_master_send - issue a single I2C message in master transmit mode
+ * @client: Handle to slave device
+ * @buf: Data that will be written to the slave
+ * @count: How many bytes to write
+ *
+ * Returns negative errno, or else the number of bytes written.
+ */
 int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
 {
        int ret;
@@ -995,6 +1063,14 @@ int i2c_master_send(struct i2c_client *client,const char *buf ,int count)
 }
 EXPORT_SYMBOL(i2c_master_send);
 
+/**
+ * i2c_master_recv - issue a single I2C message in master receive mode
+ * @client: Handle to slave device
+ * @buf: Where to store data read from slave
+ * @count: How many bytes to read
+ *
+ * Returns negative errno, or else the number of bytes read.
+ */
 int i2c_master_recv(struct i2c_client *client, char *buf ,int count)
 {
        struct i2c_adapter *adap=client->adapter;
@@ -1103,7 +1179,7 @@ int i2c_probe(struct i2c_adapter *adapter,
 
                dev_warn(&adapter->dev, "SMBus Quick command not supported, "
                         "can't probe for chips\n");
-               return -1;
+               return -EOPNOTSUPP;
        }
 
        /* Probe entries are done second, and are not affected by ignore
@@ -1157,6 +1233,179 @@ int i2c_probe(struct i2c_adapter *adapter,
 }
 EXPORT_SYMBOL(i2c_probe);
 
+/* Separate detection function for new-style drivers */
+static int i2c_detect_address(struct i2c_client *temp_client, int kind,
+                             struct i2c_driver *driver)
+{
+       struct i2c_board_info info;
+       struct i2c_adapter *adapter = temp_client->adapter;
+       int addr = temp_client->addr;
+       int err;
+
+       /* Make sure the address is valid */
+       if (addr < 0x03 || addr > 0x77) {
+               dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n",
+                        addr);
+               return -EINVAL;
+       }
+
+       /* Skip if already in use */
+       if (i2c_check_addr(adapter, addr))
+               return 0;
+
+       /* Make sure there is something at this address, unless forced */
+       if (kind < 0) {
+               if (i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+                                  I2C_SMBUS_QUICK, NULL) < 0)
+                       return 0;
+
+               /* prevent 24RF08 corruption */
+               if ((addr & ~0x0f) == 0x50)
+                       i2c_smbus_xfer(adapter, addr, 0, 0, 0,
+                                      I2C_SMBUS_QUICK, NULL);
+       }
+
+       /* Finally call the custom detection function */
+       memset(&info, 0, sizeof(struct i2c_board_info));
+       info.addr = addr;
+       err = driver->detect(temp_client, kind, &info);
+       if (err) {
+               /* -ENODEV is returned if the detection fails. We catch it
+                  here as this isn't an error. */
+               return err == -ENODEV ? 0 : err;
+       }
+
+       /* Consistency check */
+       if (info.type[0] == '\0') {
+               dev_err(&adapter->dev, "%s detection function provided "
+                       "no name for 0x%x\n", driver->driver.name,
+                       addr);
+       } else {
+               struct i2c_client *client;
+
+               /* Detection succeeded, instantiate the device */
+               dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n",
+                       info.type, info.addr);
+               client = i2c_new_device(adapter, &info);
+               if (client)
+                       list_add_tail(&client->detected, &driver->clients);
+               else
+                       dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n",
+                               info.type, info.addr);
+       }
+       return 0;
+}
+
+static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
+{
+       const struct i2c_client_address_data *address_data;
+       struct i2c_client *temp_client;
+       int i, err = 0;
+       int adap_id = i2c_adapter_id(adapter);
+
+       address_data = driver->address_data;
+       if (!driver->detect || !address_data)
+               return 0;
+
+       /* Set up a temporary client to help detect callback */
+       temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL);
+       if (!temp_client)
+               return -ENOMEM;
+       temp_client->adapter = adapter;
+
+       /* Force entries are done first, and are not affected by ignore
+          entries */
+       if (address_data->forces) {
+               const unsigned short * const *forces = address_data->forces;
+               int kind;
+
+               for (kind = 0; forces[kind]; kind++) {
+                       for (i = 0; forces[kind][i] != I2C_CLIENT_END;
+                            i += 2) {
+                               if (forces[kind][i] == adap_id
+                                || forces[kind][i] == ANY_I2C_BUS) {
+                                       dev_dbg(&adapter->dev, "found force "
+                                               "parameter for adapter %d, "
+                                               "addr 0x%02x, kind %d\n",
+                                               adap_id, forces[kind][i + 1],
+                                               kind);
+                                       temp_client->addr = forces[kind][i + 1];
+                                       err = i2c_detect_address(temp_client,
+                                               kind, driver);
+                                       if (err)
+                                               goto exit_free;
+                               }
+                       }
+               }
+       }
+
+       /* Stop here if we can't use SMBUS_QUICK */
+       if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_QUICK)) {
+               if (address_data->probe[0] == I2C_CLIENT_END
+                && address_data->normal_i2c[0] == I2C_CLIENT_END)
+                       goto exit_free;
+
+               dev_warn(&adapter->dev, "SMBus Quick command not supported, "
+                        "can't probe for chips\n");
+               err = -EOPNOTSUPP;
+               goto exit_free;
+       }
+
+       /* Stop here if the classes do not match */
+       if (!(adapter->class & driver->class))
+               goto exit_free;
+
+       /* Probe entries are done second, and are not affected by ignore
+          entries either */
+       for (i = 0; address_data->probe[i] != I2C_CLIENT_END; i += 2) {
+               if (address_data->probe[i] == adap_id
+                || address_data->probe[i] == ANY_I2C_BUS) {
+                       dev_dbg(&adapter->dev, "found probe parameter for "
+                               "adapter %d, addr 0x%02x\n", adap_id,
+                               address_data->probe[i + 1]);
+                       temp_client->addr = address_data->probe[i + 1];
+                       err = i2c_detect_address(temp_client, -1, driver);
+                       if (err)
+                               goto exit_free;
+               }
+       }
+
+       /* Normal entries are done last, unless shadowed by an ignore entry */
+       for (i = 0; address_data->normal_i2c[i] != I2C_CLIENT_END; i += 1) {
+               int j, ignore;
+
+               ignore = 0;
+               for (j = 0; address_data->ignore[j] != I2C_CLIENT_END;
+                    j += 2) {
+                       if ((address_data->ignore[j] == adap_id ||
+                            address_data->ignore[j] == ANY_I2C_BUS)
+                        && address_data->ignore[j + 1]
+                           == address_data->normal_i2c[i]) {
+                               dev_dbg(&adapter->dev, "found ignore "
+                                       "parameter for adapter %d, "
+                                       "addr 0x%02x\n", adap_id,
+                                       address_data->ignore[j + 1]);
+                               ignore = 1;
+                               break;
+                       }
+               }
+               if (ignore)
+                       continue;
+
+               dev_dbg(&adapter->dev, "found normal entry for adapter %d, "
+                       "addr 0x%02x\n", adap_id,
+                       address_data->normal_i2c[i]);
+               temp_client->addr = address_data->normal_i2c[i];
+               err = i2c_detect_address(temp_client, -1, driver);
+               if (err)
+                       goto exit_free;
+       }
+
+ exit_free:
+       kfree(temp_client);
+       return err;
+}
+
 struct i2c_client *
 i2c_new_probed_device(struct i2c_adapter *adap,
                      struct i2c_board_info *info,
@@ -1295,29 +1544,38 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg)
        if (rpec != cpec) {
                pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n",
                        rpec, cpec);
-               return -1;
+               return -EBADMSG;
        }
        return 0;
 }
 
-s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value)
-{
-       return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                             value,0,I2C_SMBUS_QUICK,NULL);
-}
-EXPORT_SYMBOL(i2c_smbus_write_quick);
-
+/**
+ * i2c_smbus_read_byte - SMBus "receive byte" protocol
+ * @client: Handle to slave device
+ *
+ * This executes the SMBus "receive byte" protocol, returning negative errno
+ * else the byte received from the device.
+ */
 s32 i2c_smbus_read_byte(struct i2c_client *client)
 {
        union i2c_smbus_data data;
-       if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                          I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data))
-               return -1;
-       else
-               return data.byte;
+       int status;
+
+       status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                               I2C_SMBUS_READ, 0,
+                               I2C_SMBUS_BYTE, &data);
+       return (status < 0) ? status : data.byte;
 }
 EXPORT_SYMBOL(i2c_smbus_read_byte);
 
+/**
+ * i2c_smbus_write_byte - SMBus "send byte" protocol
+ * @client: Handle to slave device
+ * @value: Byte to be sent
+ *
+ * This executes the SMBus "send byte" protocol, returning negative errno
+ * else zero on success.
+ */
 s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 {
        return i2c_smbus_xfer(client->adapter,client->addr,client->flags,
@@ -1325,17 +1583,35 @@ s32 i2c_smbus_write_byte(struct i2c_client *client, u8 value)
 }
 EXPORT_SYMBOL(i2c_smbus_write_byte);
 
+/**
+ * i2c_smbus_read_byte_data - SMBus "read byte" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ *
+ * This executes the SMBus "read byte" protocol, returning negative errno
+ * else a data byte received from the device.
+ */
 s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command)
 {
        union i2c_smbus_data data;
-       if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                          I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data))
-               return -1;
-       else
-               return data.byte;
+       int status;
+
+       status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                               I2C_SMBUS_READ, command,
+                               I2C_SMBUS_BYTE_DATA, &data);
+       return (status < 0) ? status : data.byte;
 }
 EXPORT_SYMBOL(i2c_smbus_read_byte_data);
 
+/**
+ * i2c_smbus_write_byte_data - SMBus "write byte" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @value: Byte being written
+ *
+ * This executes the SMBus "write byte" protocol, returning negative errno
+ * else zero on success.
+ */
 s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
 {
        union i2c_smbus_data data;
@@ -1346,17 +1622,35 @@ s32 i2c_smbus_write_byte_data(struct i2c_client *client, u8 command, u8 value)
 }
 EXPORT_SYMBOL(i2c_smbus_write_byte_data);
 
+/**
+ * i2c_smbus_read_word_data - SMBus "read word" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ *
+ * This executes the SMBus "read word" protocol, returning negative errno
+ * else a 16-bit unsigned "word" received from the device.
+ */
 s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command)
 {
        union i2c_smbus_data data;
-       if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                          I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data))
-               return -1;
-       else
-               return data.word;
+       int status;
+
+       status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                               I2C_SMBUS_READ, command,
+                               I2C_SMBUS_WORD_DATA, &data);
+       return (status < 0) ? status : data.word;
 }
 EXPORT_SYMBOL(i2c_smbus_read_word_data);
 
+/**
+ * i2c_smbus_write_word_data - SMBus "write word" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @value: 16-bit "word" being written
+ *
+ * This executes the SMBus "write word" protocol, returning negative errno
+ * else zero on success.
+ */
 s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 {
        union i2c_smbus_data data;
@@ -1368,15 +1662,14 @@ s32 i2c_smbus_write_word_data(struct i2c_client *client, u8 command, u16 value)
 EXPORT_SYMBOL(i2c_smbus_write_word_data);
 
 /**
- * i2c_smbus_read_block_data - SMBus block read request
+ * i2c_smbus_read_block_data - SMBus "block read" protocol
  * @client: Handle to slave device
- * @command: Command byte issued to let the slave know what data should
- *     be returned
+ * @command: Byte interpreted by slave
  * @values: Byte array into which data will be read; big enough to hold
  *     the data returned by the slave.  SMBus allows at most 32 bytes.
  *
- * Returns the number of bytes read in the slave's response, else a
- * negative number to indicate some kind of error.
+ * This executes the SMBus "block read" protocol, returning negative errno
+ * else the number of data bytes in the slave's response.
  *
  * Note that using this function requires that the client's adapter support
  * the I2C_FUNC_SMBUS_READ_BLOCK_DATA functionality.  Not all adapter drivers
@@ -1387,17 +1680,29 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command,
                              u8 *values)
 {
        union i2c_smbus_data data;
+       int status;
 
-       if (i2c_smbus_xfer(client->adapter, client->addr, client->flags,
-                          I2C_SMBUS_READ, command,
-                          I2C_SMBUS_BLOCK_DATA, &data))
-               return -1;
+       status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                               I2C_SMBUS_READ, command,
+                               I2C_SMBUS_BLOCK_DATA, &data);
+       if (status)
+               return status;
 
        memcpy(values, &data.block[1], data.block[0]);
        return data.block[0];
 }
 EXPORT_SYMBOL(i2c_smbus_read_block_data);
 
+/**
+ * i2c_smbus_write_block_data - SMBus "block write" protocol
+ * @client: Handle to slave device
+ * @command: Byte interpreted by slave
+ * @length: Size of data block; SMBus allows at most 32 bytes
+ * @values: Byte array which will be written.
+ *
+ * This executes the SMBus "block write" protocol, returning negative errno
+ * else zero on success.
+ */
 s32 i2c_smbus_write_block_data(struct i2c_client *client, u8 command,
                               u8 length, const u8 *values)
 {
@@ -1418,14 +1723,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command,
                                  u8 length, u8 *values)
 {
        union i2c_smbus_data data;
+       int status;
 
        if (length > I2C_SMBUS_BLOCK_MAX)
                length = I2C_SMBUS_BLOCK_MAX;
        data.block[0] = length;
-       if (i2c_smbus_xfer(client->adapter,client->addr,client->flags,
-                             I2C_SMBUS_READ,command,
-                             I2C_SMBUS_I2C_BLOCK_DATA,&data))
-               return -1;
+       status = i2c_smbus_xfer(client->adapter, client->addr, client->flags,
+                               I2C_SMBUS_READ, command,
+                               I2C_SMBUS_I2C_BLOCK_DATA, &data);
+       if (status < 0)
+               return status;
 
        memcpy(values, &data.block[1], data.block[0]);
        return data.block[0];
@@ -1466,6 +1773,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                                };
        int i;
        u8 partial_pec = 0;
+       int status;
 
        msgbuf0[0] = command;
        switch(size) {
@@ -1515,10 +1823,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                } else {
                        msg[0].len = data->block[0] + 2;
                        if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) {
-                               dev_err(&adapter->dev, "smbus_access called with "
-                                      "invalid block write size (%d)\n",
-                                      data->block[0]);
-                               return -1;
+                               dev_err(&adapter->dev,
+                                       "Invalid block write size %d\n",
+                                       data->block[0]);
+                               return -EINVAL;
                        }
                        for (i = 1; i < msg[0].len; i++)
                                msgbuf0[i] = data->block[i-1];
@@ -1528,10 +1836,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                num = 2; /* Another special case */
                read_write = I2C_SMBUS_READ;
                if (data->block[0] > I2C_SMBUS_BLOCK_MAX) {
-                       dev_err(&adapter->dev, "%s called with invalid "
-                               "block proc call size (%d)\n", __func__,
+                       dev_err(&adapter->dev,
+                               "Invalid block write size %d\n",
                                data->block[0]);
-                       return -1;
+                       return -EINVAL;
                }
                msg[0].len = data->block[0] + 2;
                for (i = 1; i < msg[0].len; i++)
@@ -1546,19 +1854,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                } else {
                        msg[0].len = data->block[0] + 1;
                        if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) {
-                               dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with "
-                                      "invalid block write size (%d)\n",
-                                      data->block[0]);
-                               return -1;
+                               dev_err(&adapter->dev,
+                                       "Invalid block write size %d\n",
+                                       data->block[0]);
+                               return -EINVAL;
                        }
                        for (i = 1; i <= data->block[0]; i++)
                                msgbuf0[i] = data->block[i];
                }
                break;
        default:
-               dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n",
-                      size);
-               return -1;
+               dev_err(&adapter->dev, "Unsupported transaction %d\n", size);
+               return -EOPNOTSUPP;
        }
 
        i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK
@@ -1576,13 +1883,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
                        msg[num-1].len++;
        }
 
-       if (i2c_transfer(adapter, msg, num) < 0)
-               return -1;
+       status = i2c_transfer(adapter, msg, num);
+       if (status < 0)
+               return status;
 
        /* Check PEC if last message is a read */
        if (i && (msg[num-1].flags & I2C_M_RD)) {
-               if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0)
-                       return -1;
+               status = i2c_smbus_check_pec(partial_pec, &msg[num-1]);
+               if (status < 0)
+                       return status;
        }
 
        if (read_write == I2C_SMBUS_READ)
@@ -1610,9 +1919,21 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr,
        return 0;
 }
 
-
+/**
+ * i2c_smbus_xfer - execute SMBus protocol operations
+ * @adapter: Handle to I2C bus
+ * @addr: Address of SMBus slave on that bus
+ * @flags: I2C_CLIENT_* flags (usually zero or I2C_CLIENT_PEC)
+ * @read_write: I2C_SMBUS_READ or I2C_SMBUS_WRITE
+ * @command: Byte interpreted by slave, for protocols which use such bytes
+ * @protocol: SMBus protocol operation to execute, such as I2C_SMBUS_PROC_CALL
+ * @data: Data to be read or written
+ *
+ * This executes an SMBus protocol operation, and returns a negative
+ * errno code else zero on success.
+ */
 s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
-                   char read_write, u8 command, int size,
+                  char read_write, u8 command, int protocol,
                    union i2c_smbus_data * data)
 {
        s32 res;
@@ -1622,11 +1943,11 @@ s32 i2c_smbus_xfer(struct i2c_adapter * adapter, u16 addr, unsigned short flags,
        if (adapter->algo->smbus_xfer) {
                mutex_lock(&adapter->bus_lock);
                res = adapter->algo->smbus_xfer(adapter,addr,flags,read_write,
-                                               command,size,data);
+                                               command, protocol, data);
                mutex_unlock(&adapter->bus_lock);
        } else
                res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
-                                             command,size,data);
+                                             command, protocol, data);
 
        return res;
 }
index 006a5857256a15b9cebab931d5c9489a62ed891d..86727fa8858fcf808a1a1373efe0ecc46a2e5678 100644 (file)
@@ -367,8 +367,7 @@ static noinline int i2cdev_ioctl_smbus(struct i2c_client *client,
        return res;
 }
 
-static int i2cdev_ioctl(struct inode *inode, struct file *file,
-               unsigned int cmd, unsigned long arg)
+static long i2cdev_ioctl(struct file *file, unsigned int cmd, unsigned long arg)
 {
        struct i2c_client *client = (struct i2c_client *)file->private_data;
        unsigned long funcs;
@@ -497,7 +496,7 @@ static const struct file_operations i2cdev_fops = {
        .llseek         = no_llseek,
        .read           = i2cdev_read,
        .write          = i2cdev_write,
-       .ioctl          = i2cdev_ioctl,
+       .unlocked_ioctl = i2cdev_ioctl,
        .open           = i2cdev_open,
        .release        = i2cdev_release,
 };
@@ -559,19 +558,12 @@ static int i2cdev_detach_adapter(struct i2c_adapter *adap)
        return 0;
 }
 
-static int i2cdev_detach_client(struct i2c_client *client)
-{
-       return 0;
-}
-
 static struct i2c_driver i2cdev_driver = {
        .driver = {
                .name   = "dev_driver",
        },
-       .id             = I2C_DRIVERID_I2CDEV,
        .attach_adapter = i2cdev_attach_adapter,
        .detach_adapter = i2cdev_detach_adapter,
-       .detach_client  = i2cdev_detach_client,
 };
 
 /* ------------------------------------------------------------------------- */
index a0df63289b5f83ed9007be92df25c9c5f7065b4c..0cf96eb8a60f610b3fc26f0bc827453eb1c201fc 100644 (file)
@@ -106,6 +106,7 @@ unsigned char *fb_ddc_read(struct i2c_adapter *adapter)
        algo_data->setsda(algo_data->data, 1);
        algo_data->setscl(algo_data->data, 1);
 
+       adapter->class |= I2C_CLASS_DDC;
        return edid;
 }
 
index ca95f09d8b43f7e9f88ddf7681e361f386493c0c..fcf9fadbf5722d328f521af00aa8fe5675e16da0 100644 (file)
@@ -100,7 +100,8 @@ static int intelfb_gpio_getsda(void *data)
 
 static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
                                 struct intelfb_i2c_chan *chan,
-                                const u32 reg, const char *name)
+                                const u32 reg, const char *name,
+                                int class)
 {
        int rc;
 
@@ -108,6 +109,7 @@ static int intelfb_setup_i2c_bus(struct intelfb_info *dinfo,
        chan->reg                       = reg;
        snprintf(chan->adapter.name, sizeof(chan->adapter.name),
                 "intelfb %s", name);
+       chan->adapter.class             = class;
        chan->adapter.owner             = THIS_MODULE;
        chan->adapter.id                = I2C_HW_B_INTELFB;
        chan->adapter.algo_data         = &chan->algo;
@@ -145,7 +147,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
 
        /* setup the DDC bus for analog output */
        intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus, GPIOA,
-                             "CRTDDC_A");
+                             "CRTDDC_A", I2C_CLASS_DDC);
        i++;
 
        /* need to add the output busses for each device
@@ -159,9 +161,9 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
        case INTEL_865G:
                dinfo->output[i].type = INTELFB_OUTPUT_DVO;
                intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].ddc_bus,
-                                     GPIOD, "DVODDC_D");
+                                     GPIOD, "DVODDC_D", I2C_CLASS_DDC);
                intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
-                                     GPIOE, "DVOI2C_E");
+                                     GPIOE, "DVOI2C_E", 0);
                i++;
                break;
        case INTEL_915G:
@@ -174,7 +176,7 @@ void intelfb_create_i2c_busses(struct intelfb_info *dinfo)
                /* SDVO ports have a single control bus - 2 devices */
                dinfo->output[i].type = INTELFB_OUTPUT_SDVO;
                intelfb_setup_i2c_bus(dinfo, &dinfo->output[i].i2c_bus,
-                                     GPIOE, "SDVOCTRL_E");
+                                     GPIOE, "SDVOCTRL_E", 0);
                /* TODO: initialize the SDVO */
                /* I830SDVOInit(pScrn, i, DVOB); */
                i++;
index 4baab7be58de4f075de0f197ac5b019da3d35eb4..75ee5a12e549ec703a0974c984975c1cdf2ac29a 100644 (file)
@@ -104,7 +104,9 @@ static struct i2c_algo_bit_data matrox_i2c_algo_template =
 };
 
 static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo, 
-               unsigned int data, unsigned int clock, const char* name) {
+               unsigned int data, unsigned int clock, const char *name,
+               int class)
+{
        int err;
 
        b->minfo = minfo;
@@ -114,6 +116,7 @@ static int i2c_bus_reg(struct i2c_bit_adapter* b, struct matrox_fb_info* minfo,
        snprintf(b->adapter.name, sizeof(b->adapter.name), name,
                minfo->fbcon.node);
        i2c_set_adapdata(&b->adapter, b);
+       b->adapter.class = class;
        b->adapter.algo_data = &b->bac;
        b->adapter.dev.parent = &ACCESS_FBINFO(pcidev)->dev;
        b->bac = matrox_i2c_algo_template;
@@ -159,22 +162,29 @@ static void* i2c_matroxfb_probe(struct matrox_fb_info* minfo) {
        switch (ACCESS_FBINFO(chip)) {
                case MGA_2064:
                case MGA_2164:
-                       err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1B_DATA, DDC1B_CLK, "DDC:fb%u #0");
+                       err = i2c_bus_reg(&m2info->ddc1, minfo,
+                                         DDC1B_DATA, DDC1B_CLK,
+                                         "DDC:fb%u #0", I2C_CLASS_DDC);
                        break;
                default:
-                       err = i2c_bus_reg(&m2info->ddc1, minfo, DDC1_DATA, DDC1_CLK, "DDC:fb%u #0");
+                       err = i2c_bus_reg(&m2info->ddc1, minfo,
+                                         DDC1_DATA, DDC1_CLK,
+                                         "DDC:fb%u #0", I2C_CLASS_DDC);
                        break;
        }
        if (err)
                goto fail_ddc1;
        if (ACCESS_FBINFO(devflags.dualhead)) {
-               err = i2c_bus_reg(&m2info->ddc2, minfo, DDC2_DATA, DDC2_CLK, "DDC:fb%u #1");
+               err = i2c_bus_reg(&m2info->ddc2, minfo,
+                                 DDC2_DATA, DDC2_CLK,
+                                 "DDC:fb%u #1", I2C_CLASS_DDC);
                if (err == -ENODEV) {
                        printk(KERN_INFO "i2c-matroxfb: VGA->TV plug detected, DDC unavailable.\n");
                } else if (err)
                        printk(KERN_INFO "i2c-matroxfb: Could not register secondary output i2c bus. Continuing anyway.\n");
                /* Register maven bus even on G450/G550 */
-               err = i2c_bus_reg(&m2info->maven, minfo, MAT_DATA, MAT_CLK, "MAVEN:fb%u");
+               err = i2c_bus_reg(&m2info->maven, minfo,
+                                 MAT_DATA, MAT_CLK, "MAVEN:fb%u", 0);
                if (err)
                        printk(KERN_INFO "i2c-matroxfb: Could not register Maven i2c bus. Continuing anyway.\n");
        }
index 77afbb60fd1185fb76699eacd9a8ba6fd5f7f919..0177d280f733df0837f7635b6413b2ff0a23202a 100644 (file)
@@ -33,9 +33,11 @@ struct i2c_algo_pcf_data {
        int  (*getclock) (void *data);
        void (*waitforpin) (void);
 
-       /* local settings */
-       int udelay;
-       int timeout;
+       /* Multi-master lost arbitration back-off delay (msecs)
+        * This should be set by the bus adapter or knowledgable client
+        * if bus is multi-mastered, else zero
+        */
+       unsigned long lab_mdelay;
 };
 
 int i2c_pcf_add_bus(struct i2c_adapter *);
index 580acc93903e63795a23c1efee2dddbc23cab7b0..ef13b7c66df32bd5fdbf2c5aa2ee1e0d8fb17a2e 100644 (file)
@@ -91,8 +91,6 @@
 #define I2C_DRIVERID_M52790    95      /* Mitsubishi M52790SP/FP AV switch */
 #define I2C_DRIVERID_CS5345    96      /* cs5345 audio processor       */
 
-#define I2C_DRIVERID_I2CDEV    900
-
 #define I2C_DRIVERID_OV7670 1048       /* Omnivision 7670 camera */
 
 /*
 #define I2C_HW_B_RIVA          0x010010 /* Riva based graphics cards */
 #define I2C_HW_B_IOC           0x010011 /* IOC bit-wiggling */
 #define I2C_HW_B_IXP2000       0x010016 /* GPIO on IXP2000 systems */
-#define I2C_HW_B_S3VIA         0x010018 /* S3Via ProSavage adapter */
 #define I2C_HW_B_ZR36067       0x010019 /* Zoran-36057/36067 based boards */
 #define I2C_HW_B_PCILYNX       0x01001a /* TI PCILynx I2C adapter */
 #define I2C_HW_B_CX2388x       0x01001b /* connexant 2388x based tv cards */
index 8dc7301321926f6f4a6e9454dcd50d9aa9d1722f..08be0d21864c6fcd81dd667baee289b81edf20e5 100644 (file)
@@ -35,6 +35,8 @@
 #include <linux/sched.h>       /* for completion */
 #include <linux/mutex.h>
 
+extern struct bus_type i2c_bus_type;
+
 /* --- General options ------------------------------------------------        */
 
 struct i2c_msg;
@@ -43,6 +45,7 @@ struct i2c_adapter;
 struct i2c_client;
 struct i2c_driver;
 union i2c_smbus_data;
+struct i2c_board_info;
 
 /*
  * The master routines are the ones normally used to transmit data to devices
@@ -69,9 +72,8 @@ extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr,
                            union i2c_smbus_data * data);
 
 /* Now follow the 'nice' access routines. These also document the calling
-   conventions of smbus_access. */
+   conventions of i2c_smbus_xfer. */
 
-extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value);
 extern s32 i2c_smbus_read_byte(struct i2c_client * client);
 extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value);
 extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command);
@@ -93,15 +95,33 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client,
                                          u8 command, u8 length,
                                          const u8 *values);
 
-/*
- * A driver is capable of handling one or more physical devices present on
- * I2C adapters. This information is used to inform the driver of adapter
- * events.
+/**
+ * struct i2c_driver - represent an I2C device driver
+ * @class: What kind of i2c device we instantiate (for detect)
+ * @detect: Callback for device detection
+ * @address_data: The I2C addresses to probe, ignore or force (for detect)
+ * @clients: List of detected clients we created (for i2c-core use only)
  *
  * The driver.owner field should be set to the module owner of this driver.
  * The driver.name field should be set to the name of this driver.
+ *
+ * For automatic device detection, both @detect and @address_data must
+ * be defined. @class should also be set, otherwise only devices forced
+ * with module parameters will be created. The detect function must
+ * fill at least the name field of the i2c_board_info structure it is
+ * handed upon successful detection, and possibly also the flags field.
+ *
+ * If @detect is missing, the driver will still work fine for enumerated
+ * devices. Detected devices simply won't be supported. This is expected
+ * for the many I2C/SMBus devices which can't be detected reliably, and
+ * the ones which can always be enumerated in practice.
+ *
+ * The i2c_client structure which is handed to the @detect callback is
+ * not a real i2c_client. It is initialized just enough so that you can
+ * call i2c_smbus_read_byte_data and friends on it. Don't do anything
+ * else with it. In particular, calling dev_dbg and friends on it is
+ * not allowed.
  */
-
 struct i2c_driver {
        int id;
        unsigned int class;
@@ -141,6 +161,11 @@ struct i2c_driver {
 
        struct device_driver driver;
        const struct i2c_device_id *id_table;
+
+       /* Device detection callback for automatic device creation */
+       int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *);
+       const struct i2c_client_address_data *address_data;
+       struct list_head clients;
 };
 #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver)
 
@@ -156,6 +181,7 @@ struct i2c_driver {
  * @dev: Driver model device node for the slave.
  * @irq: indicates the IRQ generated by this device (if any)
  * @list: list of active/busy clients (DEPRECATED)
+ * @detected: member of an i2c_driver.clients list
  * @released: used to synchronize client releases & detaches and references
  *
  * An i2c_client identifies a single device (i.e. chip) connected to an
@@ -173,6 +199,7 @@ struct i2c_client {
        struct device dev;              /* the device structure         */
        int irq;                        /* irq issued by device         */
        struct list_head list;          /* DEPRECATED */
+       struct list_head detected;
        struct completion released;
 };
 #define to_i2c_client(d) container_of(d, struct i2c_client, dev)
@@ -350,10 +377,11 @@ static inline void i2c_set_adapdata (struct i2c_adapter *dev, void *data)
 #define I2C_CLASS_HWMON                (1<<0)  /* lm_sensors, ... */
 #define I2C_CLASS_TV_ANALOG    (1<<1)  /* bttv + friends */
 #define I2C_CLASS_TV_DIGITAL   (1<<2)  /* dvb cards */
-#define I2C_CLASS_DDC          (1<<3)  /* i2c-matroxfb ? */
+#define I2C_CLASS_DDC          (1<<3)  /* DDC bus on graphics adapters */
 #define I2C_CLASS_CAM_ANALOG   (1<<4)  /* camera with analog CCD */
 #define I2C_CLASS_CAM_DIGITAL  (1<<5)  /* most webcams */
 #define I2C_CLASS_SOUND                (1<<6)  /* sound devices */
+#define I2C_CLASS_SPD          (1<<7)  /* SPD EEPROMs and similar */
 #define I2C_CLASS_ALL          (UINT_MAX) /* all of the above */
 
 /* i2c_client_address_data is the struct for holding default client
@@ -537,7 +565,7 @@ union i2c_smbus_data {
                               /* and one more for user-space compatibility */
 };
 
-/* smbus_access read or write markers */
+/* i2c_smbus_xfer read or write markers */
 #define I2C_SMBUS_READ 1
 #define I2C_SMBUS_WRITE        0
 
diff --git a/include/linux/i2c/at24.h b/include/linux/i2c/at24.h
new file mode 100644 (file)
index 0000000..f6edd52
--- /dev/null
@@ -0,0 +1,28 @@
+#ifndef _LINUX_AT24_H
+#define _LINUX_AT24_H
+
+#include <linux/types.h>
+
+/*
+ * As seen through Linux I2C, differences between the most common types of I2C
+ * memory include:
+ * - How much memory is available (usually specified in bit)?
+ * - What write page size does it support?
+ * - Special flags (16 bit addresses, read_only, world readable...)?
+ *
+ * If you set up a custom eeprom type, please double-check the parameters.
+ * Especially page_size needs extra care, as you risk data loss if your value
+ * is bigger than what the chip actually supports!
+ */
+
+struct at24_platform_data {
+       u32             byte_len;               /* size (sum of all addr) */
+       u16             page_size;              /* for writes */
+       u8              flags;
+#define AT24_FLAG_ADDR16       0x80    /* address pointer is 16 bit */
+#define AT24_FLAG_READONLY     0x40    /* sysfs-entry will be read-only */
+#define AT24_FLAG_IRUGO                0x20    /* sysfs-entry will be world-readable */
+#define AT24_FLAG_TAKE8ADDR    0x10    /* take always 8 addresses (24c00) */
+};
+
+#endif /* _LINUX_AT24_H */