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
This commit is contained in:
Коммит
41440ffe21
|
@ -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.
|
||||
|
|
|
@ -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.
|
|
@ -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
|
||||
|
|
|
@ -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".
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 = {
|
||||
|
|
|
@ -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
|
||||
#define INIT3 0x4
|
||||
|
||||
/* delays */
|
||||
#define CYCLE_DELAY 10
|
||||
#define TIMEOUT (HZ / 2)
|
||||
|
||||
|
||||
static void __iomem *ioaddr;
|
||||
|
||||
/* The voo GPIO registers don't have individual masks for each bit
|
||||
so we always have to read before writing. */
|
||||
|
||||
static void bit_vooi2c_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_vooi2c_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_vooi2c_getscl(void *data)
|
||||
{
|
||||
return (0 != (readl(ioaddr + REG) & I2C_SCL_IN));
|
||||
}
|
||||
|
||||
static int bit_vooi2c_getsda(void *data)
|
||||
{
|
||||
return (0 != (readl(ioaddr + REG) & I2C_SDA_IN));
|
||||
}
|
||||
|
||||
static void bit_vooddc_setscl(void *data, int val)
|
||||
{
|
||||
unsigned int r;
|
||||
r = readl(ioaddr + REG);
|
||||
if (val)
|
||||
r |= DDC_SCL_OUT;
|
||||
else
|
||||
r &= ~DDC_SCL_OUT;
|
||||
writel(r, ioaddr + REG);
|
||||
readl(ioaddr + REG); /* flush posted write */
|
||||
}
|
||||
|
||||
static void bit_vooddc_setsda(void *data, int val)
|
||||
{
|
||||
unsigned int r;
|
||||
r = readl(ioaddr + REG);
|
||||
if (val)
|
||||
r |= DDC_SDA_OUT;
|
||||
else
|
||||
r &= ~DDC_SDA_OUT;
|
||||
writel(r, ioaddr + REG);
|
||||
readl(ioaddr + REG); /* flush posted write */
|
||||
}
|
||||
|
||||
static int bit_vooddc_getscl(void *data)
|
||||
{
|
||||
return (0 != (readl(ioaddr + REG) & DDC_SCL_IN));
|
||||
}
|
||||
|
||||
static int bit_vooddc_getsda(void *data)
|
||||
{
|
||||
return (0 != (readl(ioaddr + REG) & DDC_SDA_IN));
|
||||
}
|
||||
|
||||
static int config_v3(struct pci_dev *dev)
|
||||
{
|
||||
unsigned long cadr;
|
||||
|
||||
/* map Voodoo3 memory */
|
||||
cadr = dev->resource[0].start;
|
||||
cadr &= PCI_BASE_ADDRESS_MEM_MASK;
|
||||
ioaddr = ioremap_nocache(cadr, 0x1000);
|
||||
if (ioaddr) {
|
||||
writel(0x8160, ioaddr + REG2);
|
||||
writel(0xcffc0020, ioaddr + REG);
|
||||
dev_info(&dev->dev, "Using Banshee/Voodoo3 I2C device at %p\n", ioaddr);
|
||||
return 0;
|
||||
}
|
||||
return -ENODEV;
|
||||
}
|
||||
|
||||
static struct i2c_algo_bit_data voo_i2c_bit_data = {
|
||||
.setsda = bit_vooi2c_setsda,
|
||||
.setscl = bit_vooi2c_setscl,
|
||||
.getsda = bit_vooi2c_getsda,
|
||||
.getscl = bit_vooi2c_getscl,
|
||||
.udelay = CYCLE_DELAY,
|
||||
.timeout = TIMEOUT
|
||||
};
|
||||
|
||||
static struct i2c_adapter voodoo3_i2c_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.name = "I2C Voodoo3/Banshee adapter",
|
||||
.algo_data = &voo_i2c_bit_data,
|
||||
};
|
||||
|
||||
static struct i2c_algo_bit_data voo_ddc_bit_data = {
|
||||
.setsda = bit_vooddc_setsda,
|
||||
.setscl = bit_vooddc_setscl,
|
||||
.getsda = bit_vooddc_getsda,
|
||||
.getscl = bit_vooddc_getscl,
|
||||
.udelay = CYCLE_DELAY,
|
||||
.timeout = TIMEOUT
|
||||
};
|
||||
|
||||
static struct i2c_adapter voodoo3_ddc_adapter = {
|
||||
.owner = THIS_MODULE,
|
||||
.class = I2C_CLASS_DDC,
|
||||
.name = "DDC Voodoo3/Banshee adapter",
|
||||
.algo_data = &voo_ddc_bit_data,
|
||||
};
|
||||
|
||||
static struct pci_device_id voodoo3_ids[] __devinitdata = {
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_VOODOO3) },
|
||||
{ PCI_DEVICE(PCI_VENDOR_ID_3DFX, PCI_DEVICE_ID_3DFX_BANSHEE) },
|
||||
{ 0, }
|
||||
};
|
||||
|
||||
MODULE_DEVICE_TABLE (pci, voodoo3_ids);
|
||||
|
||||
static int __devinit voodoo3_probe(struct pci_dev *dev, const struct pci_device_id *id)
|
||||
{
|
||||
int retval;
|
||||
|
||||
retval = config_v3(dev);
|
||||
if (retval)
|
||||
return retval;
|
||||
|
||||
/* set up the sysfs linkage to our parent device */
|
||||
voodoo3_i2c_adapter.dev.parent = &dev->dev;
|
||||
voodoo3_ddc_adapter.dev.parent = &dev->dev;
|
||||
|
||||
retval = i2c_bit_add_bus(&voodoo3_i2c_adapter);
|
||||
if (retval)
|
||||
return retval;
|
||||
retval = i2c_bit_add_bus(&voodoo3_ddc_adapter);
|
||||
if (retval)
|
||||
i2c_del_adapter(&voodoo3_i2c_adapter);
|
||||
return retval;
|
||||
}
|
||||
|
||||
static void __devexit voodoo3_remove(struct pci_dev *dev)
|
||||
{
|
||||
i2c_del_adapter(&voodoo3_i2c_adapter);
|
||||
i2c_del_adapter(&voodoo3_ddc_adapter);
|
||||
iounmap(ioaddr);
|
||||
}
|
||||
|
||||
static struct pci_driver voodoo3_driver = {
|
||||
.name = "voodoo3_smbus",
|
||||
.id_table = voodoo3_ids,
|
||||
.probe = voodoo3_probe,
|
||||
.remove = __devexit_p(voodoo3_remove),
|
||||
};
|
||||
|
||||
static int __init i2c_voodoo3_init(void)
|
||||
{
|
||||
return pci_register_driver(&voodoo3_driver);
|
||||
}
|
||||
|
||||
static void __exit i2c_voodoo3_exit(void)
|
||||
{
|
||||
pci_unregister_driver(&voodoo3_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("Voodoo3 I2C/SMBus driver");
|
||||
MODULE_LICENSE("GPL");
|
||||
|
||||
module_init(i2c_voodoo3_init);
|
||||
module_exit(i2c_voodoo3_exit);
|
|
@ -6,16 +6,6 @@
|
|||
|
||||
menu "Miscellaneous I2C Chip support"
|
||||
|
||||
config DS1682
|
||||
tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
|
||||
depends on EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1682 Total Elapsed Time Recorder.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called ds1682.
|
||||
|
||||
config SENSORS_TSL2550
|
||||
tristate "Taos TSL2550 ambient light sensor"
|
||||
depends on EXPERIMENTAL
|
||||
|
|
|
@ -10,7 +10,6 @@
|
|||
# * I/O expander drivers go to drivers/gpio
|
||||
#
|
||||
|
||||
obj-$(CONFIG_DS1682) += ds1682.o
|
||||
obj-$(CONFIG_SENSORS_TSL2550) += tsl2550.o
|
||||
|
||||
ifeq ($(CONFIG_I2C_DEBUG_CHIP),y)
|
||||
|
|
|
@ -558,11 +558,9 @@ static void i2c_scan_static_board_info(struct i2c_adapter *adapter)
|
|||
up_read(&__i2c_board_lock);
|
||||
}
|
||||
|
||||
static int i2c_do_add_adapter(struct device_driver *d, void *data)
|
||||
static int i2c_do_add_adapter(struct i2c_driver *driver,
|
||||
struct i2c_adapter *adap)
|
||||
{
|
||||
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);
|
||||
|
||||
|
@ -574,6 +572,11 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __process_new_adapter(struct device_driver *d, void *data)
|
||||
{
|
||||
return i2c_do_add_adapter(to_i2c_driver(d), data);
|
||||
}
|
||||
|
||||
static int i2c_register_adapter(struct i2c_adapter *adap)
|
||||
{
|
||||
int res = 0, dummy;
|
||||
|
@ -584,7 +587,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
|||
goto out_list;
|
||||
}
|
||||
|
||||
mutex_init(&adap->bus_lock);
|
||||
rt_mutex_init(&adap->bus_lock);
|
||||
|
||||
/* Set default timeout to 1 second if not already set */
|
||||
if (adap->timeout == 0)
|
||||
|
@ -614,7 +617,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap)
|
|||
/* Notify drivers */
|
||||
mutex_lock(&core_lock);
|
||||
dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap,
|
||||
i2c_do_add_adapter);
|
||||
__process_new_adapter);
|
||||
mutex_unlock(&core_lock);
|
||||
|
||||
return 0;
|
||||
|
@ -715,10 +718,9 @@ retry:
|
|||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_add_numbered_adapter);
|
||||
|
||||
static int i2c_do_del_adapter(struct device_driver *d, void *data)
|
||||
static int i2c_do_del_adapter(struct i2c_driver *driver,
|
||||
struct i2c_adapter *adapter)
|
||||
{
|
||||
struct i2c_driver *driver = to_i2c_driver(d);
|
||||
struct i2c_adapter *adapter = data;
|
||||
struct i2c_client *client, *_n;
|
||||
int res;
|
||||
|
||||
|
@ -750,6 +752,11 @@ static int __unregister_client(struct device *dev, void *dummy)
|
|||
return 0;
|
||||
}
|
||||
|
||||
static int __process_removed_adapter(struct device_driver *d, void *data)
|
||||
{
|
||||
return i2c_do_del_adapter(to_i2c_driver(d), data);
|
||||
}
|
||||
|
||||
/**
|
||||
* i2c_del_adapter - unregister I2C adapter
|
||||
* @adap: the adapter being unregistered
|
||||
|
@ -777,7 +784,7 @@ int i2c_del_adapter(struct i2c_adapter *adap)
|
|||
/* Tell drivers about this removal */
|
||||
mutex_lock(&core_lock);
|
||||
res = bus_for_each_drv(&i2c_bus_type, NULL, adap,
|
||||
i2c_do_del_adapter);
|
||||
__process_removed_adapter);
|
||||
mutex_unlock(&core_lock);
|
||||
if (res)
|
||||
return res;
|
||||
|
@ -826,22 +833,11 @@ EXPORT_SYMBOL(i2c_del_adapter);
|
|||
|
||||
/* ------------------------------------------------------------------------- */
|
||||
|
||||
static int __attach_adapter(struct device *dev, void *data)
|
||||
static int __process_new_driver(struct device *dev, void *data)
|
||||
{
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_driver *driver = data;
|
||||
|
||||
if (dev->type != &i2c_adapter_type)
|
||||
return 0;
|
||||
adapter = to_i2c_adapter(dev);
|
||||
|
||||
i2c_detect(adapter, driver);
|
||||
|
||||
/* Legacy drivers scan i2c busses directly */
|
||||
if (driver->attach_adapter)
|
||||
driver->attach_adapter(adapter);
|
||||
|
||||
return 0;
|
||||
return i2c_do_add_adapter(data, to_i2c_adapter(dev));
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -873,40 +869,18 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver)
|
|||
INIT_LIST_HEAD(&driver->clients);
|
||||
/* Walk the adapters that are already present */
|
||||
mutex_lock(&core_lock);
|
||||
bus_for_each_dev(&i2c_bus_type, NULL, driver, __attach_adapter);
|
||||
bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_new_driver);
|
||||
mutex_unlock(&core_lock);
|
||||
|
||||
return 0;
|
||||
}
|
||||
EXPORT_SYMBOL(i2c_register_driver);
|
||||
|
||||
static int __detach_adapter(struct device *dev, void *data)
|
||||
static int __process_removed_driver(struct device *dev, void *data)
|
||||
{
|
||||
struct i2c_adapter *adapter;
|
||||
struct i2c_driver *driver = data;
|
||||
struct i2c_client *client, *_n;
|
||||
|
||||
if (dev->type != &i2c_adapter_type)
|
||||
return 0;
|
||||
adapter = to_i2c_adapter(dev);
|
||||
|
||||
/* Remove the devices we created ourselves as the result of hardware
|
||||
* probing (using a driver's detect method) */
|
||||
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);
|
||||
}
|
||||
|
||||
if (driver->detach_adapter) {
|
||||
if (driver->detach_adapter(adapter))
|
||||
dev_err(&adapter->dev,
|
||||
"detach_adapter failed for driver [%s]\n",
|
||||
driver->driver.name);
|
||||
}
|
||||
|
||||
return 0;
|
||||
return i2c_do_del_adapter(data, to_i2c_adapter(dev));
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -917,7 +891,7 @@ static int __detach_adapter(struct device *dev, void *data)
|
|||
void i2c_del_driver(struct i2c_driver *driver)
|
||||
{
|
||||
mutex_lock(&core_lock);
|
||||
bus_for_each_dev(&i2c_bus_type, NULL, driver, __detach_adapter);
|
||||
bus_for_each_dev(&i2c_bus_type, NULL, driver, __process_removed_driver);
|
||||
mutex_unlock(&core_lock);
|
||||
|
||||
driver_unregister(&driver->driver);
|
||||
|
@ -1092,12 +1066,12 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
#endif
|
||||
|
||||
if (in_atomic() || irqs_disabled()) {
|
||||
ret = mutex_trylock(&adap->bus_lock);
|
||||
ret = rt_mutex_trylock(&adap->bus_lock);
|
||||
if (!ret)
|
||||
/* I2C activity is ongoing. */
|
||||
return -EAGAIN;
|
||||
} else {
|
||||
mutex_lock_nested(&adap->bus_lock, adap->level);
|
||||
rt_mutex_lock(&adap->bus_lock);
|
||||
}
|
||||
|
||||
/* Retry automatically on arbitration loss */
|
||||
|
@ -1109,7 +1083,7 @@ int i2c_transfer(struct i2c_adapter *adap, struct i2c_msg *msgs, int num)
|
|||
if (time_after(jiffies, orig_jiffies + adap->timeout))
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&adap->bus_lock);
|
||||
rt_mutex_unlock(&adap->bus_lock);
|
||||
|
||||
return ret;
|
||||
} else {
|
||||
|
@ -1180,7 +1154,7 @@ EXPORT_SYMBOL(i2c_master_recv);
|
|||
* ----------------------------------------------------
|
||||
*/
|
||||
|
||||
static int i2c_detect_address(struct i2c_client *temp_client, int kind,
|
||||
static int i2c_detect_address(struct i2c_client *temp_client,
|
||||
struct i2c_driver *driver)
|
||||
{
|
||||
struct i2c_board_info info;
|
||||
|
@ -1199,22 +1173,18 @@ static int i2c_detect_address(struct i2c_client *temp_client, int kind,
|
|||
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;
|
||||
/* Make sure there is something at this address */
|
||||
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);
|
||||
}
|
||||
/* 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);
|
||||
err = driver->detect(temp_client, -1, &info);
|
||||
if (err) {
|
||||
/* -ENODEV is returned if the detection fails. We catch it
|
||||
here as this isn't an error. */
|
||||
|
@ -1259,40 +1229,13 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
|
|||
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 the classes do not match */
|
||||
if (!(adapter->class & driver->class))
|
||||
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)
|
||||
if (address_data->normal_i2c[0] == I2C_CLIENT_END)
|
||||
goto exit_free;
|
||||
|
||||
dev_warn(&adapter->dev, "SMBus Quick command not supported, "
|
||||
|
@ -1301,48 +1244,12 @@ static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver)
|
|||
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);
|
||||
err = i2c_detect_address(temp_client, driver);
|
||||
if (err)
|
||||
goto exit_free;
|
||||
}
|
||||
|
@ -1913,7 +1820,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
|
|||
flags &= I2C_M_TEN | I2C_CLIENT_PEC;
|
||||
|
||||
if (adapter->algo->smbus_xfer) {
|
||||
mutex_lock(&adapter->bus_lock);
|
||||
rt_mutex_lock(&adapter->bus_lock);
|
||||
|
||||
/* Retry automatically on arbitration loss */
|
||||
orig_jiffies = jiffies;
|
||||
|
@ -1927,7 +1834,7 @@ s32 i2c_smbus_xfer(struct i2c_adapter *adapter, u16 addr, unsigned short flags,
|
|||
orig_jiffies + adapter->timeout))
|
||||
break;
|
||||
}
|
||||
mutex_unlock(&adapter->bus_lock);
|
||||
rt_mutex_unlock(&adapter->bus_lock);
|
||||
} else
|
||||
res = i2c_smbus_xfer_emulated(adapter,addr,flags,read_write,
|
||||
command, protocol, data);
|
||||
|
|
|
@ -34,7 +34,6 @@
|
|||
#include <linux/list.h>
|
||||
#include <linux/i2c.h>
|
||||
#include <linux/i2c-dev.h>
|
||||
#include <linux/smp_lock.h>
|
||||
#include <linux/jiffies.h>
|
||||
#include <asm/uaccess.h>
|
||||
|
||||
|
@ -445,20 +444,14 @@ static int i2cdev_open(struct inode *inode, struct file *file)
|
|||
struct i2c_client *client;
|
||||
struct i2c_adapter *adap;
|
||||
struct i2c_dev *i2c_dev;
|
||||
int ret = 0;
|
||||
|
||||
lock_kernel();
|
||||
i2c_dev = i2c_dev_get_by_minor(minor);
|
||||
if (!i2c_dev) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (!i2c_dev)
|
||||
return -ENODEV;
|
||||
|
||||
adap = i2c_get_adapter(i2c_dev->adap->nr);
|
||||
if (!adap) {
|
||||
ret = -ENODEV;
|
||||
goto out;
|
||||
}
|
||||
if (!adap)
|
||||
return -ENODEV;
|
||||
|
||||
/* This creates an anonymous i2c_client, which may later be
|
||||
* pointed to some address using I2C_SLAVE or I2C_SLAVE_FORCE.
|
||||
|
@ -470,8 +463,7 @@ static int i2cdev_open(struct inode *inode, struct file *file)
|
|||
client = kzalloc(sizeof(*client), GFP_KERNEL);
|
||||
if (!client) {
|
||||
i2c_put_adapter(adap);
|
||||
ret = -ENOMEM;
|
||||
goto out;
|
||||
return -ENOMEM;
|
||||
}
|
||||
snprintf(client->name, I2C_NAME_SIZE, "i2c-dev %d", adap->nr);
|
||||
client->driver = &i2cdev_driver;
|
||||
|
@ -479,9 +471,7 @@ static int i2cdev_open(struct inode *inode, struct file *file)
|
|||
client->adapter = adap;
|
||||
file->private_data = client;
|
||||
|
||||
out:
|
||||
unlock_kernel();
|
||||
return ret;
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int i2cdev_release(struct inode *inode, struct file *file)
|
||||
|
|
|
@ -246,6 +246,16 @@ config EP93XX_PWM
|
|||
To compile this driver as a module, choose M here: the module will
|
||||
be called ep93xx_pwm.
|
||||
|
||||
config DS1682
|
||||
tristate "Dallas DS1682 Total Elapsed Time Recorder with Alarm"
|
||||
depends on I2C && EXPERIMENTAL
|
||||
help
|
||||
If you say yes here you get support for Dallas Semiconductor
|
||||
DS1682 Total Elapsed Time Recorder.
|
||||
|
||||
This driver can also be built as a module. If so, the module
|
||||
will be called ds1682.
|
||||
|
||||
source "drivers/misc/c2port/Kconfig"
|
||||
source "drivers/misc/eeprom/Kconfig"
|
||||
source "drivers/misc/cb710/Kconfig"
|
||||
|
|
|
@ -20,6 +20,7 @@ obj-$(CONFIG_SGI_GRU) += sgi-gru/
|
|||
obj-$(CONFIG_HP_ILO) += hpilo.o
|
||||
obj-$(CONFIG_ISL29003) += isl29003.o
|
||||
obj-$(CONFIG_EP93XX_PWM) += ep93xx_pwm.o
|
||||
obj-$(CONFIG_DS1682) += ds1682.o
|
||||
obj-$(CONFIG_C2PORT) += c2port/
|
||||
obj-$(CONFIG_IWMC3200TOP) += iwmc3200top/
|
||||
obj-y += eeprom/
|
||||
|
|
|
@ -417,32 +417,25 @@ static int ics932s401_detect(struct i2c_client *client, int kind,
|
|||
struct i2c_board_info *info)
|
||||
{
|
||||
struct i2c_adapter *adapter = client->adapter;
|
||||
int vendor, device, revision;
|
||||
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA))
|
||||
return -ENODEV;
|
||||
|
||||
if (kind <= 0) {
|
||||
int vendor, device, revision;
|
||||
vendor = i2c_smbus_read_word_data(client, ICS932S401_REG_VENDOR_REV);
|
||||
vendor >>= 8;
|
||||
revision = vendor >> ICS932S401_REV_SHIFT;
|
||||
vendor &= ICS932S401_VENDOR_MASK;
|
||||
if (vendor != ICS932S401_VENDOR)
|
||||
return -ENODEV;
|
||||
|
||||
vendor = i2c_smbus_read_word_data(client,
|
||||
ICS932S401_REG_VENDOR_REV);
|
||||
vendor >>= 8;
|
||||
revision = vendor >> ICS932S401_REV_SHIFT;
|
||||
vendor &= ICS932S401_VENDOR_MASK;
|
||||
if (vendor != ICS932S401_VENDOR)
|
||||
return -ENODEV;
|
||||
device = i2c_smbus_read_word_data(client, ICS932S401_REG_DEVICE);
|
||||
device >>= 8;
|
||||
if (device != ICS932S401_DEVICE)
|
||||
return -ENODEV;
|
||||
|
||||
device = i2c_smbus_read_word_data(client,
|
||||
ICS932S401_REG_DEVICE);
|
||||
device >>= 8;
|
||||
if (device != ICS932S401_DEVICE)
|
||||
return -ENODEV;
|
||||
|
||||
if (revision != ICS932S401_REV)
|
||||
dev_info(&adapter->dev, "Unknown revision %d\n",
|
||||
revision);
|
||||
} else
|
||||
dev_dbg(&adapter->dev, "detection forced\n");
|
||||
if (revision != ICS932S401_REV)
|
||||
dev_info(&adapter->dev, "Unknown revision %d\n", revision);
|
||||
|
||||
strlcpy(info->type, "ics932s401", I2C_NAME_SIZE);
|
||||
|
||||
|
|
|
@ -110,7 +110,7 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client *client,
|
|||
* @driver: Device driver model driver
|
||||
* @id_table: List of I2C devices supported by this driver
|
||||
* @detect: Callback for device detection
|
||||
* @address_data: The I2C addresses to probe, ignore or force (for detect)
|
||||
* @address_data: The I2C addresses to probe (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.
|
||||
|
@ -338,8 +338,7 @@ struct i2c_adapter {
|
|||
void *algo_data;
|
||||
|
||||
/* data fields that are valid for all devices */
|
||||
u8 level; /* nesting level for lockdep */
|
||||
struct mutex bus_lock;
|
||||
struct rt_mutex bus_lock;
|
||||
|
||||
int timeout; /* in jiffies */
|
||||
int retries;
|
||||
|
@ -367,7 +366,7 @@ static inline void i2c_set_adapdata(struct i2c_adapter *dev, void *data)
|
|||
*/
|
||||
static inline void i2c_lock_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
mutex_lock(&adapter->bus_lock);
|
||||
rt_mutex_lock(&adapter->bus_lock);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -376,7 +375,7 @@ static inline void i2c_lock_adapter(struct i2c_adapter *adapter)
|
|||
*/
|
||||
static inline void i2c_unlock_adapter(struct i2c_adapter *adapter)
|
||||
{
|
||||
mutex_unlock(&adapter->bus_lock);
|
||||
rt_mutex_unlock(&adapter->bus_lock);
|
||||
}
|
||||
|
||||
/*flags for the client struct: */
|
||||
|
@ -398,9 +397,6 @@ static inline void i2c_unlock_adapter(struct i2c_adapter *adapter)
|
|||
*/
|
||||
struct i2c_client_address_data {
|
||||
const unsigned short *normal_i2c;
|
||||
const unsigned short *probe;
|
||||
const unsigned short *ignore;
|
||||
const unsigned short * const *forces;
|
||||
};
|
||||
|
||||
/* Internal numbers to terminate lists */
|
||||
|
@ -614,134 +610,48 @@ union i2c_smbus_data {
|
|||
module_param_array(var, short, &var##_num, 0); \
|
||||
MODULE_PARM_DESC(var, desc)
|
||||
|
||||
#define I2C_CLIENT_MODULE_PARM_FORCE(name) \
|
||||
I2C_CLIENT_MODULE_PARM(force_##name, \
|
||||
"List of adapter,address pairs which are " \
|
||||
"unquestionably assumed to contain a `" \
|
||||
# name "' chip")
|
||||
|
||||
|
||||
#define I2C_CLIENT_INSMOD_COMMON \
|
||||
I2C_CLIENT_MODULE_PARM(probe, "List of adapter,address pairs to scan " \
|
||||
"additionally"); \
|
||||
I2C_CLIENT_MODULE_PARM(ignore, "List of adapter,address pairs not to " \
|
||||
"scan"); \
|
||||
static const struct i2c_client_address_data addr_data = { \
|
||||
.normal_i2c = normal_i2c, \
|
||||
.probe = probe, \
|
||||
.ignore = ignore, \
|
||||
.forces = forces, \
|
||||
}
|
||||
|
||||
#define I2C_CLIENT_FORCE_TEXT \
|
||||
"List of adapter,address pairs to boldly assume to be present"
|
||||
|
||||
/* These are the ones you want to use in your own drivers. Pick the one
|
||||
which matches the number of devices the driver differenciates between. */
|
||||
#define I2C_CLIENT_INSMOD \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
static const unsigned short * const forces[] = { force, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_1(chip1) \
|
||||
enum chips { any_chip, chip1 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_2(chip1, chip2) \
|
||||
enum chips { any_chip, chip1, chip2 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_3(chip1, chip2, chip3) \
|
||||
enum chips { any_chip, chip1, chip2, chip3 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, force_##chip3, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_4(chip1, chip2, chip3, chip4) \
|
||||
enum chips { any_chip, chip1, chip2, chip3, chip4 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, force_##chip3, \
|
||||
force_##chip4, NULL}; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_5(chip1, chip2, chip3, chip4, chip5) \
|
||||
enum chips { any_chip, chip1, chip2, chip3, chip4, chip5 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, force_##chip3, \
|
||||
force_##chip4, force_##chip5, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_6(chip1, chip2, chip3, chip4, chip5, chip6) \
|
||||
enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip6); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, force_##chip3, \
|
||||
force_##chip4, force_##chip5, force_##chip6, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_7(chip1, chip2, chip3, chip4, chip5, chip6, chip7) \
|
||||
enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \
|
||||
chip7 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip6); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip7); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, force_##chip3, \
|
||||
force_##chip4, force_##chip5, force_##chip6, \
|
||||
force_##chip7, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
|
||||
#define I2C_CLIENT_INSMOD_8(chip1, chip2, chip3, chip4, chip5, chip6, chip7, chip8) \
|
||||
enum chips { any_chip, chip1, chip2, chip3, chip4, chip5, chip6, \
|
||||
chip7, chip8 }; \
|
||||
I2C_CLIENT_MODULE_PARM(force, I2C_CLIENT_FORCE_TEXT); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip1); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip2); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip3); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip4); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip5); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip6); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip7); \
|
||||
I2C_CLIENT_MODULE_PARM_FORCE(chip8); \
|
||||
static const unsigned short * const forces[] = { force, \
|
||||
force_##chip1, force_##chip2, force_##chip3, \
|
||||
force_##chip4, force_##chip5, force_##chip6, \
|
||||
force_##chip7, force_##chip8, NULL }; \
|
||||
I2C_CLIENT_INSMOD_COMMON
|
||||
#endif /* __KERNEL__ */
|
||||
#endif /* _LINUX_I2C_H */
|
||||
|
|
Загрузка…
Ссылка в новой задаче