diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 08:12:16 -0800 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2009-12-08 08:12:16 -0800 |
commit | 41440ffe21f29bdb985cab76b2d0b06d83e63b19 (patch) | |
tree | 1d7d1ff6f699ccbabb71c7bc4172f7d15bc4bc45 | |
parent | dad3de7d0090280f44ff27131ed2878f1ab6ddad (diff) | |
parent | 6471b68982d3bb1a593c3e183c804ecf830125d3 (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
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 |