aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 08:12:16 -0800
committerLinus Torvalds <torvalds@linux-foundation.org>2009-12-08 08:12:16 -0800
commit41440ffe21f29bdb985cab76b2d0b06d83e63b19 (patch)
tree1d7d1ff6f699ccbabb71c7bc4172f7d15bc4bc45
parentdad3de7d0090280f44ff27131ed2878f1ab6ddad (diff)
parent6471b68982d3bb1a593c3e183c804ecf830125d3 (diff)
Merge branch 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging
* 'i2c-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/jdelvare/staging: i2c-stub: Documentation update i2c-stub: Allow user to disable some commands i2c-stub: Implement I2C block support i2c: Refactor for_each callbacks i2c-i801: Retry on lost arbitration i2c: Remove big kernel lock from i2cdev_open ics932s401: Clean up detect function i2c: Simplify i2c_detect_address i2c: Drop probe, ignore and force module parameters i2c: Add missing __devinit markers to old i2c adapter drivers i2c: Bus drivers don't have to support I2C_M_REV_DIR_ADDR i2c: Prevent priority inversion on top of bus lock i2c-voodoo3: Delete i2c-powermac: Drop temporary name buffer i2c-powermac: Include the i2c_adapter in struct pmac_i2c_bus i2c-powermac: Log errors i2c-powermac: Refactor i2c_powermac_smbus_xfer i2c-powermac: Reject unsupported I2C transactions i2c/chips: Move ds1682 to drivers/misc
-rw-r--r--Documentation/feature-removal-schedule.txt9
-rw-r--r--Documentation/i2c/busses/i2c-voodoo362
-rw-r--r--Documentation/i2c/i2c-stub16
-rw-r--r--Documentation/i2c/old-module-parameters44
-rw-r--r--arch/powerpc/include/asm/pmac_low_i2c.h6
-rw-r--r--arch/powerpc/platforms/powermac/low_i2c.c25
-rw-r--r--drivers/i2c/Kconfig1
-rw-r--r--drivers/i2c/busses/Kconfig16
-rw-r--r--drivers/i2c/busses/Makefile3
-rw-r--r--drivers/i2c/busses/i2c-ali1535.c2
-rw-r--r--drivers/i2c/busses/i2c-ali15x3.c2
-rw-r--r--drivers/i2c/busses/i2c-i801.c3
-rw-r--r--drivers/i2c/busses/i2c-iop3xx.c6
-rw-r--r--drivers/i2c/busses/i2c-mv64xxx.c3
-rw-r--r--drivers/i2c/busses/i2c-powermac.c139
-rw-r--r--drivers/i2c/busses/i2c-sis5595.c2
-rw-r--r--drivers/i2c/busses/i2c-sis630.c2
-rw-r--r--drivers/i2c/busses/i2c-stub.c34
-rw-r--r--drivers/i2c/busses/i2c-voodoo3.c248
-rw-r--r--drivers/i2c/chips/Kconfig10
-rw-r--r--drivers/i2c/chips/Makefile1
-rw-r--r--drivers/i2c/i2c-core.c169
-rw-r--r--drivers/i2c/i2c-dev.c22
-rw-r--r--drivers/misc/Kconfig10
-rw-r--r--drivers/misc/Makefile1
-rw-r--r--drivers/misc/ds1682.c (renamed from drivers/i2c/chips/ds1682.c)0
-rw-r--r--drivers/misc/ics932s401.c37
-rw-r--r--include/linux/i2c.h98
28 files changed, 248 insertions, 723 deletions
diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt
index a004b04ffd3..591e94448e6 100644
--- a/Documentation/feature-removal-schedule.txt
+++ b/Documentation/feature-removal-schedule.txt
@@ -407,15 +407,6 @@ Who: Alex Chiang <achiang@hp.com>
---------------------------
-What: i2c-voodoo3 driver
-When: October 2009
-Why: Superseded by tdfxfb. I2C/DDC support used to live in a separate
- driver but this caused driver conflicts.
-Who: Jean Delvare <khali@linux-fr.org>
- Krzysztof Helt <krzysztof.h1@wp.pl>
-
----------------------------
-
What: CONFIG_RFKILL_INPUT
When: 2.6.33
Why: Should be implemented in userspace, policy daemon.
diff --git a/Documentation/i2c/busses/i2c-voodoo3 b/Documentation/i2c/busses/i2c-voodoo3
deleted file mode 100644
index 62d90a454d3..00000000000
--- a/Documentation/i2c/busses/i2c-voodoo3
+++ /dev/null
@@ -1,62 +0,0 @@
-Kernel driver i2c-voodoo3
-
-Supported adapters:
- * 3dfx Voodoo3 based cards
- * Voodoo Banshee based cards
-
-Authors:
- Frodo Looijaard <frodol@dds.nl>,
- Philip Edelbrock <phil@netroedge.com>,
- Ralph Metzler <rjkm@thp.uni-koeln.de>,
- Mark D. Studebaker <mdsxyz123@yahoo.com>
-
-Main contact: Philip Edelbrock <phil@netroedge.com>
-
-The code is based upon Ralph's test code (he did the hard stuff ;')
-
-Description
------------
-
-The 3dfx Voodoo3 chip contains 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. The intent by 3dfx was
-to allow manufacturers to add extra chips to the video card such as a
-TV-out chip such as the BT869 or possibly even I2C based temperature
-sensors like the ADM1021 or LM75.
-
-Stability
----------
-
-Seems to be stable on the test machine, but needs more testing on other
-machines. Simultaneous accesses of the DDC and I2C busses may cause errors.
-
-Supported Devices
------------------
-
-Specifically, this driver was written and tested on the '3dfx Voodoo3 AGP
-3000' which has a tv-out feature (s-video or composite). According to the
-docs and discussions, this code should work for any Voodoo3 based cards as
-well as Voodoo Banshee based cards. The DDC interface has been tested on a
-Voodoo Banshee card.
-
-Issues
-------
-
-Probably many, but it seems to work OK on my system. :')
-
-
-External Device Connection
---------------------------
-
-The digital video input jumpers give availability to the I2C bus.
-Specifically, pins 13 and 25 (bottom row middle, and bottom right-end) are
-the I2C clock and I2C data lines, respectively. +5V and GND are probably
-also easily available making the addition of extra I2C/SMBus devices easy
-to implement.
diff --git a/Documentation/i2c/i2c-stub b/Documentation/i2c/i2c-stub
index 0d8be1c20c1..fa4b669c166 100644
--- a/Documentation/i2c/i2c-stub
+++ b/Documentation/i2c/i2c-stub
@@ -2,9 +2,9 @@ MODULE: i2c-stub
DESCRIPTION:
-This module is a very simple fake I2C/SMBus driver. It implements four
-types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, and
-(r/w) word data.
+This module is a very simple fake I2C/SMBus driver. It implements five
+types of SMBus commands: write quick, (r/w) byte, (r/w) byte data, (r/w)
+word data, and (r/w) I2C block data.
You need to provide chip addresses as a module parameter when loading this
driver, which will then only react to SMBus commands to these addresses.
@@ -21,8 +21,8 @@ EEPROMs, among others.
The typical use-case is like this:
1. load this module
- 2. use i2cset (from lm_sensors project) to pre-load some data
- 3. load the target sensors chip driver module
+ 2. use i2cset (from the i2c-tools project) to pre-load some data
+ 3. load the target chip driver module
4. observe its behavior in the kernel log
There's a script named i2c-stub-from-dump in the i2c-tools package which
@@ -33,6 +33,12 @@ PARAMETERS:
int chip_addr[10]:
The SMBus addresses to emulate chips at.
+unsigned long functionality:
+ Functionality override, to disable some commands. See I2C_FUNC_*
+ constants in <linux/i2c.h> for the suitable values. For example,
+ value 0x1f0000 would only enable the quick, byte and byte data
+ commands.
+
CAVEATS:
If your target driver polls some byte or word waiting for it to change, the
diff --git a/Documentation/i2c/old-module-parameters b/Documentation/i2c/old-module-parameters
new file mode 100644
index 00000000000..8e2b629d533
--- /dev/null
+++ b/Documentation/i2c/old-module-parameters
@@ -0,0 +1,44 @@
+I2C device driver binding control from user-space
+=================================================
+
+Up to kernel 2.6.32, many i2c drivers used helper macros provided by
+<linux/i2c.h> which created standard module parameters to let the user
+control how the driver would probe i2c buses and attach to devices. These
+parameters were known as "probe" (to let the driver probe for an extra
+address), "force" (to forcibly attach the driver to a given device) and
+"ignore" (to prevent a driver from probing a given address).
+
+With the conversion of the i2c subsystem to the standard device driver
+binding model, it became clear that these per-module parameters were no
+longer needed, and that a centralized implementation was possible. The new,
+sysfs-based interface is described in the documentation file
+"instantiating-devices", section "Method 4: Instantiate from user-space".
+
+Below is a mapping from the old module parameters to the new interface.
+
+Attaching a driver to an I2C device
+-----------------------------------
+
+Old method (module parameters):
+# modprobe <driver> probe=1,0x2d
+# modprobe <driver> force=1,0x2d
+# modprobe <driver> force_<device>=1,0x2d
+
+New method (sysfs interface):
+# echo <device> 0x2d > /sys/bus/i2c/devices/i2c-1/new_device
+
+Preventing a driver from attaching to an I2C device
+---------------------------------------------------
+
+Old method (module parameters):
+# modprobe <driver> ignore=1,0x2f
+
+New method (sysfs interface):
+# echo dummy 0x2f > /sys/bus/i2c/devices/i2c-1/new_device
+# modprobe <driver>
+
+Of course, it is important to instantiate the "dummy" device before loading
+the driver. The dummy device will be handled by i2c-core itself, preventing
+other drivers from binding to it later on. If there is a real device at the
+problematic address, and you want another driver to bind to it, then simply
+pass the name of the device in question instead of "dummy".
diff --git a/arch/powerpc/include/asm/pmac_low_i2c.h b/arch/powerpc/include/asm/pmac_low_i2c.h
index 131011bd7e7..01d71826d92 100644
--- a/arch/powerpc/include/asm/pmac_low_i2c.h
+++ b/arch/powerpc/include/asm/pmac_low_i2c.h
@@ -72,11 +72,7 @@ extern int pmac_i2c_get_type(struct pmac_i2c_bus *bus);
extern int pmac_i2c_get_flags(struct pmac_i2c_bus *bus);
extern int pmac_i2c_get_channel(struct pmac_i2c_bus *bus);
-/* i2c layer adapter attach/detach */
-extern void pmac_i2c_attach_adapter(struct pmac_i2c_bus *bus,
- struct i2c_adapter *adapter);
-extern void pmac_i2c_detach_adapter(struct pmac_i2c_bus *bus,
- struct i2c_adapter *adapter);
+/* i2c layer adapter helpers */
extern struct i2c_adapter *pmac_i2c_get_adapter(struct pmac_i2c_bus *bus);
extern struct pmac_i2c_bus *pmac_i2c_adapter_to_bus(struct i2c_adapter *adapter);
diff --git a/arch/powerpc/platforms/powermac/low_i2c.c b/arch/powerpc/platforms/powermac/low_i2c.c
index 414ca9849f2..345e2da5676 100644
--- a/arch/powerpc/platforms/powermac/low_i2c.c
+++ b/arch/powerpc/platforms/powermac/low_i2c.c
@@ -42,6 +42,7 @@
#include <linux/interrupt.h>
#include <linux/timer.h>
#include <linux/mutex.h>
+#include <linux/i2c.h>
#include <asm/keylargo.h>
#include <asm/uninorth.h>
#include <asm/io.h>
@@ -80,7 +81,7 @@ struct pmac_i2c_bus
struct device_node *busnode;
int type;
int flags;
- struct i2c_adapter *adapter;
+ struct i2c_adapter adapter;
void *hostdata;
int channel; /* some hosts have multiple */
int mode; /* current mode */
@@ -1014,25 +1015,9 @@ int pmac_i2c_get_channel(struct pmac_i2c_bus *bus)
EXPORT_SYMBOL_GPL(pmac_i2c_get_channel);
-void pmac_i2c_attach_adapter(struct pmac_i2c_bus *bus,
- struct i2c_adapter *adapter)
-{
- WARN_ON(bus->adapter != NULL);
- bus->adapter = adapter;
-}
-EXPORT_SYMBOL_GPL(pmac_i2c_attach_adapter);
-
-void pmac_i2c_detach_adapter(struct pmac_i2c_bus *bus,
- struct i2c_adapter *adapter)
-{
- WARN_ON(bus->adapter != adapter);
- bus->adapter = NULL;
-}
-EXPORT_SYMBOL_GPL(pmac_i2c_detach_adapter);
-
struct i2c_adapter *pmac_i2c_get_adapter(struct pmac_i2c_bus *bus)
{
- return bus->adapter;
+ return &bus->adapter;
}
EXPORT_SYMBOL_GPL(pmac_i2c_get_adapter);
@@ -1041,7 +1026,7 @@ struct pmac_i2c_bus *pmac_i2c_adapter_to_bus(struct i2c_adapter *adapter)
struct pmac_i2c_bus *bus;
list_for_each_entry(bus, &pmac_i2c_busses, link)
- if (bus->adapter == adapter)
+ if (&bus->adapter == adapter)
return bus;
return NULL;
}
@@ -1053,7 +1038,7 @@ int pmac_i2c_match_adapter(struct device_node *dev, struct i2c_adapter *adapter)
if (bus == NULL)
return 0;
- return (bus->adapter == adapter);
+ return (&bus->adapter == adapter);
}
EXPORT_SYMBOL_GPL(pmac_i2c_match_adapter);
diff --git a/drivers/i2c/Kconfig b/drivers/i2c/Kconfig
index d7ece131b4f..8d8a00e5a30 100644
--- a/drivers/i2c/Kconfig
+++ b/drivers/i2c/Kconfig
@@ -5,6 +5,7 @@
menuconfig I2C
tristate "I2C support"
depends on HAS_IOMEM
+ select RT_MUTEXES
---help---
I2C (pronounce: I-square-C) is a slow serial bus protocol used in
many micro controller applications and developed by Philips. SMBus,
diff --git a/drivers/i2c/busses/Kconfig b/drivers/i2c/busses/Kconfig
index e8fe7f169e2..5f318ce2977 100644
--- a/drivers/i2c/busses/Kconfig
+++ b/drivers/i2c/busses/Kconfig
@@ -640,22 +640,6 @@ config I2C_TINY_USB
This driver can also be built as a module. If so, the module
will be called i2c-tiny-usb.
-comment "Graphics adapter I2C/DDC channel drivers"
- depends on PCI
-
-config I2C_VOODOO3
- tristate "Voodoo 3 (DEPRECATED)"
- depends on PCI
- select I2C_ALGOBIT
- help
- If you say yes to this option, support will be included for the
- Voodoo 3 I2C interface. This driver is deprecated and you should
- use the tdfxfb driver instead, which additionally provides
- framebuffer support.
-
- This driver can also be built as a module. If so, the module
- will be called i2c-voodoo3.
-
comment "Other I2C/SMBus bus drivers"
config I2C_ACORN
diff --git a/drivers/i2c/busses/Makefile b/drivers/i2c/busses/Makefile
index ff937ac69f5..302c551977b 100644
--- a/drivers/i2c/busses/Makefile
+++ b/drivers/i2c/busses/Makefile
@@ -61,9 +61,6 @@ 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
-# 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
diff --git a/drivers/i2c/busses/i2c-ali1535.c b/drivers/i2c/busses/i2c-ali1535.c
index d108450df06..8de7d7b87bb 100644
--- a/drivers/i2c/busses/i2c-ali1535.c
+++ b/drivers/i2c/busses/i2c-ali1535.c
@@ -138,7 +138,7 @@ static unsigned short ali1535_smba;
Note the differences between kernels with the old PCI BIOS interface and
newer kernels with the real PCI interface. In compat.h some things are
defined to make the transition easier. */
-static int ali1535_setup(struct pci_dev *dev)
+static int __devinit ali1535_setup(struct pci_dev *dev)
{
int retval = -ENODEV;
unsigned char temp;
diff --git a/drivers/i2c/busses/i2c-ali15x3.c b/drivers/i2c/busses/i2c-ali15x3.c
index d627fceb790..e7e3205f128 100644
--- a/drivers/i2c/busses/i2c-ali15x3.c
+++ b/drivers/i2c/busses/i2c-ali15x3.c
@@ -131,7 +131,7 @@ MODULE_PARM_DESC(force_addr,
static struct pci_driver ali15x3_driver;
static unsigned short ali15x3_smba;
-static int ali15x3_setup(struct pci_dev *ALI15X3_dev)
+static int __devinit ali15x3_setup(struct pci_dev *ALI15X3_dev)
{
u16 a;
unsigned char temp;
diff --git a/drivers/i2c/busses/i2c-i801.c b/drivers/i2c/busses/i2c-i801.c
index 55edcfe5b85..df6ab553f97 100644
--- a/drivers/i2c/busses/i2c-i801.c
+++ b/drivers/i2c/busses/i2c-i801.c
@@ -767,6 +767,9 @@ static int __devinit i801_probe(struct pci_dev *dev, const struct pci_device_id
/* set up the sysfs linkage to our parent device */
i801_adapter.dev.parent = &dev->dev;
+ /* Retry up to 3 times on lost arbitration */
+ i801_adapter.retries = 3;
+
snprintf(i801_adapter.name, sizeof(i801_adapter.name),
"SMBus I801 adapter at %04lx", i801_smba);
err = i2c_add_adapter(&i801_adapter);
diff --git a/drivers/i2c/busses/i2c-iop3xx.c b/drivers/i2c/busses/i2c-iop3xx.c
index a75c75e77b9..5901707fc66 100644
--- a/drivers/i2c/busses/i2c-iop3xx.c
+++ b/drivers/i2c/busses/i2c-iop3xx.c
@@ -56,12 +56,6 @@ iic_cook_addr(struct i2c_msg *msg)
if (msg->flags & I2C_M_RD)
addr |= 1;
- /*
- * Read or Write?
- */
- if (msg->flags & I2C_M_REV_DIR_ADDR)
- addr ^= 1;
-
return addr;
}
diff --git a/drivers/i2c/busses/i2c-mv64xxx.c b/drivers/i2c/busses/i2c-mv64xxx.c
index bbab0e16663..ed387ffa473 100644
--- a/drivers/i2c/busses/i2c-mv64xxx.c
+++ b/drivers/i2c/busses/i2c-mv64xxx.c
@@ -338,9 +338,6 @@ mv64xxx_i2c_prepare_for_io(struct mv64xxx_i2c_data *drv_data,
if (msg->flags & I2C_M_RD)
dir = 1;
- if (msg->flags & I2C_M_REV_DIR_ADDR)
- dir ^= 1;
-
if (msg->flags & I2C_M_TEN) {
drv_data->addr1 = 0xf0 | (((u32)msg->addr & 0x300) >> 7) | dir;
drv_data->addr2 = (u32)msg->addr & 0xff;
diff --git a/drivers/i2c/busses/i2c-powermac.c b/drivers/i2c/busses/i2c-powermac.c
index 3c9d71f6018..1c440a70ec6 100644
--- a/drivers/i2c/busses/i2c-powermac.c
+++ b/drivers/i2c/busses/i2c-powermac.c
@@ -49,48 +49,38 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
int rc = 0;
int read = (read_write == I2C_SMBUS_READ);
int addrdir = (addr << 1) | read;
+ int mode, subsize, len;
+ u32 subaddr;
+ u8 *buf;
u8 local[2];
- rc = pmac_i2c_open(bus, 0);
- if (rc)
- return rc;
+ if (size == I2C_SMBUS_QUICK || size == I2C_SMBUS_BYTE) {
+ mode = pmac_i2c_mode_std;
+ subsize = 0;
+ subaddr = 0;
+ } else {
+ mode = read ? pmac_i2c_mode_combined : pmac_i2c_mode_stdsub;
+ subsize = 1;
+ subaddr = command;
+ }
switch (size) {
case I2C_SMBUS_QUICK:
- rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 0, 0, NULL, 0);
+ buf = NULL;
+ len = 0;
break;
case I2C_SMBUS_BYTE:
- rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 0, 0, &data->byte, 1);
- break;
case I2C_SMBUS_BYTE_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 1, command, &data->byte, 1);
+ buf = &data->byte;
+ len = 1;
break;
case I2C_SMBUS_WORD_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
if (!read) {
local[0] = data->word & 0xff;
local[1] = (data->word >> 8) & 0xff;
}
- rc = pmac_i2c_xfer(bus, addrdir, 1, command, local, 2);
- if (rc == 0 && read) {
- data->word = ((u16)local[1]) << 8;
- data->word |= local[0];
- }
+ buf = local;
+ len = 2;
break;
/* Note that these are broken vs. the expected smbus API where
@@ -105,28 +95,44 @@ static s32 i2c_powermac_smbus_xfer( struct i2c_adapter* adap,
* a repeat start/addr phase (but not stop in between)
*/
case I2C_SMBUS_BLOCK_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 1, command, data->block,
- data->block[0] + 1);
-
+ buf = data->block;
+ len = data->block[0] + 1;
break;
case I2C_SMBUS_I2C_BLOCK_DATA:
- rc = pmac_i2c_setmode(bus, read ?
- pmac_i2c_mode_combined :
- pmac_i2c_mode_stdsub);
- if (rc)
- goto bail;
- rc = pmac_i2c_xfer(bus, addrdir, 1, command,
- &data->block[1], data->block[0]);
+ buf = &data->block[1];
+ len = data->block[0];
break;
default:
- rc = -EINVAL;
+ return -EINVAL;
+ }
+
+ rc = pmac_i2c_open(bus, 0);
+ if (rc) {
+ dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
+ return rc;
+ }
+
+ rc = pmac_i2c_setmode(bus, mode);
+ if (rc) {
+ dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
+ mode, rc);
+ goto bail;
}
+
+ rc = pmac_i2c_xfer(bus, addrdir, subsize, subaddr, buf, len);
+ if (rc) {
+ dev_err(&adap->dev,
+ "I2C transfer at 0x%02x failed, size %d, err %d\n",
+ addrdir >> 1, size, rc);
+ goto bail;
+ }
+
+ if (size == I2C_SMBUS_WORD_DATA && read) {
+ data->word = ((u16)local[1]) << 8;
+ data->word |= local[0];
+ }
+
bail:
pmac_i2c_close(bus);
return rc;
@@ -146,20 +152,33 @@ static int i2c_powermac_master_xfer( struct i2c_adapter *adap,
int read;
int addrdir;
+ if (num != 1) {
+ dev_err(&adap->dev,
+ "Multi-message I2C transactions not supported\n");
+ return -EOPNOTSUPP;
+ }
+
if (msgs->flags & I2C_M_TEN)
return -EINVAL;
read = (msgs->flags & I2C_M_RD) != 0;
addrdir = (msgs->addr << 1) | read;
- if (msgs->flags & I2C_M_REV_DIR_ADDR)
- addrdir ^= 1;
rc = pmac_i2c_open(bus, 0);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev, "Failed to open I2C, err %d\n", rc);
return rc;
+ }
rc = pmac_i2c_setmode(bus, pmac_i2c_mode_std);
- if (rc)
+ if (rc) {
+ dev_err(&adap->dev, "Failed to set I2C mode %d, err %d\n",
+ pmac_i2c_mode_std, rc);
goto bail;
+ }
rc = pmac_i2c_xfer(bus, addrdir, 0, 0, msgs->buf, msgs->len);
+ if (rc < 0)
+ dev_err(&adap->dev, "I2C %s 0x%02x failed, err %d\n",
+ addrdir & 1 ? "read from" : "write to", addrdir >> 1,
+ rc);
bail:
pmac_i2c_close(bus);
return rc < 0 ? rc : 1;
@@ -183,19 +202,16 @@ static const struct i2c_algorithm i2c_powermac_algorithm = {
static int __devexit i2c_powermac_remove(struct platform_device *dev)
{
struct i2c_adapter *adapter = platform_get_drvdata(dev);
- struct pmac_i2c_bus *bus = i2c_get_adapdata(adapter);
int rc;
rc = i2c_del_adapter(adapter);
- pmac_i2c_detach_adapter(bus, adapter);
- i2c_set_adapdata(adapter, NULL);
/* We aren't that prepared to deal with this... */
if (rc)
printk(KERN_WARNING
"i2c-powermac.c: Failed to remove bus %s !\n",
adapter->name);
platform_set_drvdata(dev, NULL);
- kfree(adapter);
+ memset(adapter, 0, sizeof(*adapter));
return 0;
}
@@ -206,12 +222,12 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
struct pmac_i2c_bus *bus = dev->dev.platform_data;
struct device_node *parent = NULL;
struct i2c_adapter *adapter;
- char name[32];
const char *basename;
int rc;
if (bus == NULL)
return -EINVAL;
+ adapter = pmac_i2c_get_adapter(bus);
/* Ok, now we need to make up a name for the interface that will
* match what we used to do in the past, that is basically the
@@ -237,29 +253,22 @@ static int __devinit i2c_powermac_probe(struct platform_device *dev)
default:
return -EINVAL;
}
- snprintf(name, 32, "%s %d", basename, pmac_i2c_get_channel(bus));
+ snprintf(adapter->name, sizeof(adapter->name), "%s %d", basename,
+ pmac_i2c_get_channel(bus));
of_node_put(parent);
- adapter = kzalloc(sizeof(struct i2c_adapter), GFP_KERNEL);
- if (adapter == NULL) {
- printk(KERN_ERR "i2c-powermac: can't allocate inteface !\n");
- return -ENOMEM;
- }
platform_set_drvdata(dev, adapter);
- strcpy(adapter->name, name);
adapter->algo = &i2c_powermac_algorithm;
i2c_set_adapdata(adapter, bus);
adapter->dev.parent = &dev->dev;
- pmac_i2c_attach_adapter(bus, adapter);
rc = i2c_add_adapter(adapter);
if (rc) {
printk(KERN_ERR "i2c-powermac: Adapter %s registration "
- "failed\n", name);
- i2c_set_adapdata(adapter, NULL);
- pmac_i2c_detach_adapter(bus, adapter);
+ "failed\n", adapter->name);
+ memset(adapter, 0, sizeof(*adapter));
}
- printk(KERN_INFO "PowerMac i2c bus %s registered\n", name);
+ printk(KERN_INFO "PowerMac i2c bus %s registered\n", adapter->name);
if (!strncmp(basename, "uni-n", 5)) {
struct device_node *np;
diff --git a/drivers/i2c/busses/i2c-sis5595.c b/drivers/i2c/busses/i2c-sis5595.c
index 139f0c7f12a..844569f7d8b 100644
--- a/drivers/i2c/busses/i2c-sis5595.c
+++ b/drivers/i2c/busses/i2c-sis5595.c
@@ -142,7 +142,7 @@ static void sis5595_write(u8 reg, u8 data)
outb(data, sis5595_base + SMB_DAT);
}
-static int sis5595_setup(struct pci_dev *SIS5595_dev)
+static int __devinit sis5595_setup(struct pci_dev *SIS5595_dev)
{
u16 a;
u8 val;
diff --git a/drivers/i2c/busses/i2c-sis630.c b/drivers/i2c/busses/i2c-sis630.c
index 70ca41e90e5..68cff7af701 100644
--- a/drivers/i2c/busses/i2c-sis630.c
+++ b/drivers/i2c/busses/i2c-sis630.c
@@ -389,7 +389,7 @@ static u32 sis630_func(struct i2c_adapter *adapter)
I2C_FUNC_SMBUS_BLOCK_DATA;
}
-static int sis630_setup(struct pci_dev *sis630_dev)
+static int __devinit sis630_setup(struct pci_dev *sis630_dev)
{
unsigned char b;
struct pci_dev *dummy = NULL;
diff --git a/drivers/i2c/busses/i2c-stub.c b/drivers/i2c/busses/i2c-stub.c
index 1b7b2af9403..0c770eabe85 100644
--- a/drivers/i2c/busses/i2c-stub.c
+++ b/drivers/i2c/busses/i2c-stub.c
@@ -35,6 +35,10 @@ module_param_array(chip_addr, ushort, NULL, S_IRUGO);
MODULE_PARM_DESC(chip_addr,
"Chip addresses (up to 10, between 0x03 and 0x77)");
+static unsigned long functionality = ~0UL;
+module_param(functionality, ulong, S_IRUGO | S_IWUSR);
+MODULE_PARM_DESC(functionality, "Override functionality bitfield");
+
struct stub_chip {
u8 pointer;
u16 words[256]; /* Byte operations use the LSB as per SMBus
@@ -48,7 +52,7 @@ 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)
{
s32 ret;
- int i;
+ int i, len;
struct stub_chip *chip = NULL;
/* Search for the right chip */
@@ -118,6 +122,29 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
ret = 0;
break;
+ case I2C_SMBUS_I2C_BLOCK_DATA:
+ len = data->block[0];
+ if (read_write == I2C_SMBUS_WRITE) {
+ for (i = 0; i < len; i++) {
+ chip->words[command + i] &= 0xff00;
+ chip->words[command + i] |= data->block[1 + i];
+ }
+ dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
+ "wrote %d bytes at 0x%02x.\n",
+ addr, len, command);
+ } else {
+ for (i = 0; i < len; i++) {
+ data->block[1 + i] =
+ chip->words[command + i] & 0xff;
+ }
+ dev_dbg(&adap->dev, "i2c block data - addr 0x%02x, "
+ "read %d bytes at 0x%02x.\n",
+ addr, len, command);
+ }
+
+ ret = 0;
+ break;
+
default:
dev_dbg(&adap->dev, "Unsupported I2C/SMBus command\n");
ret = -EOPNOTSUPP;
@@ -129,8 +156,9 @@ static s32 stub_xfer(struct i2c_adapter * adap, u16 addr, unsigned short flags,
static u32 stub_func(struct i2c_adapter *adapter)
{
- return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
- I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA;
+ return (I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
+ I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
+ I2C_FUNC_SMBUS_I2C_BLOCK) & functionality;
}
static const struct i2c_algorithm smbus_algorithm = {
diff --git a/drivers/i2c/busses/i2c-voodoo3.c b/drivers/i2c/busses/i2c-voodoo3.c
deleted file mode 100644
index 7663d57833a..00000000000
--- a/drivers/i2c/busses/i2c-voodoo3.c
+++ /dev/null
@@ -1,248 +0,0 @@
-/*
- Copyright (c) 1998, 1999 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 I2C bus of the Voodoo3 to gain access to
- the BT869 and possibly other I2C devices. */
-
-#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>
-
-/* the only registers we use */
-#define REG 0x78
-#define REG2 0x70
-
-/* bit locations in the register */
-#define DDC_ENAB 0x00040000
-#define DDC_SCL_OUT 0x00080000
-#define DDC_SDA_OUT 0x00100000
-#define DDC_SCL_IN 0x00200000
-#define DDC_SDA_IN 0x00400000
-#define I2C_ENAB 0x00800000
-#define I2C_SCL_OUT 0x01000000
-#define I2C_SDA_OUT 0x02000000
-#define I2C_SCL_IN 0x04000000
-#define I2C_SDA_IN 0x08000000
-
-/* initialization states */
-#define INIT2 0x2