mirror of
https://github.com/adulau/aha.git
synced 2024-12-29 04:06:22 +00:00
Merge branch 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6
* 'i2c-for-linus' of git://jdelvare.pck.nerim.net/jdelvare-2.6: i2c: Convert some more new-style drivers to use module aliasing i2c: Match dummy devices by type i2c-sibyte: Mark i2c_sibyte_add_bus() as static i2c-sibyte: Correct a comment about frequency i2c: Improve the functionality documentation i2c: Improve smbus-protocol documentation i2c-piix4: Blacklist two mainboards i2c-piix4: Increase the intitial delay for the ServerWorks CSB5 i2c-mpc: Compare to NO_IRQ instead of zero
This commit is contained in:
commit
5701412351
13 changed files with 191 additions and 106 deletions
|
@ -51,26 +51,38 @@ A few combinations of the above flags are also defined for your convenience:
|
||||||
the transparent emulation layer)
|
the transparent emulation layer)
|
||||||
|
|
||||||
|
|
||||||
ALGORITHM/ADAPTER IMPLEMENTATION
|
ADAPTER IMPLEMENTATION
|
||||||
--------------------------------
|
----------------------
|
||||||
|
|
||||||
When you write a new algorithm driver, you will have to implement a
|
When you write a new adapter driver, you will have to implement a
|
||||||
function callback `functionality', that gets an i2c_adapter structure
|
function callback `functionality'. Typical implementations are given
|
||||||
pointer as its only parameter:
|
below.
|
||||||
|
|
||||||
struct i2c_algorithm {
|
A typical SMBus-only adapter would list all the SMBus transactions it
|
||||||
/* Many other things of course; check <linux/i2c.h>! */
|
supports. This example comes from the i2c-piix4 driver:
|
||||||
u32 (*functionality) (struct i2c_adapter *);
|
|
||||||
}
|
|
||||||
|
|
||||||
A typically implementation is given below, from i2c-algo-bit.c:
|
static u32 piix4_func(struct i2c_adapter *adapter)
|
||||||
|
|
||||||
static u32 bit_func(struct i2c_adapter *adap)
|
|
||||||
{
|
{
|
||||||
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
|
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||||
I2C_FUNC_PROTOCOL_MANGLING;
|
I2C_FUNC_SMBUS_BYTE_DATA | I2C_FUNC_SMBUS_WORD_DATA |
|
||||||
|
I2C_FUNC_SMBUS_BLOCK_DATA;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
A typical full-I2C adapter would use the following (from the i2c-pxa
|
||||||
|
driver):
|
||||||
|
|
||||||
|
static u32 i2c_pxa_functionality(struct i2c_adapter *adap)
|
||||||
|
{
|
||||||
|
return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL;
|
||||||
|
}
|
||||||
|
|
||||||
|
I2C_FUNC_SMBUS_EMUL includes all the SMBus transactions (with the
|
||||||
|
addition of I2C block transactions) which i2c-core can emulate using
|
||||||
|
I2C_FUNC_I2C without any help from the adapter driver. The idea is
|
||||||
|
to let the client drivers check for the support of SMBus functions
|
||||||
|
without having to care whether the said functions are implemented in
|
||||||
|
hardware by the adapter, or emulated in software by i2c-core on top
|
||||||
|
of an I2C adapter.
|
||||||
|
|
||||||
|
|
||||||
CLIENT CHECKING
|
CLIENT CHECKING
|
||||||
|
@ -78,36 +90,33 @@ CLIENT CHECKING
|
||||||
|
|
||||||
Before a client tries to attach to an adapter, or even do tests to check
|
Before a client tries to attach to an adapter, or even do tests to check
|
||||||
whether one of the devices it supports is present on an adapter, it should
|
whether one of the devices it supports is present on an adapter, it should
|
||||||
check whether the needed functionality is present. There are two functions
|
check whether the needed functionality is present. The typical way to do
|
||||||
defined which should be used instead of calling the functionality hook
|
this is (from the lm75 driver):
|
||||||
in the algorithm structure directly:
|
|
||||||
|
|
||||||
/* Return the functionality mask */
|
static int lm75_detect(...)
|
||||||
extern u32 i2c_get_functionality (struct i2c_adapter *adap);
|
|
||||||
|
|
||||||
/* Return 1 if adapter supports everything we need, 0 if not. */
|
|
||||||
extern int i2c_check_functionality (struct i2c_adapter *adap, u32 func);
|
|
||||||
|
|
||||||
This is a typical way to use these functions (from the writing-clients
|
|
||||||
document):
|
|
||||||
int foo_detect_client(struct i2c_adapter *adapter, int address,
|
|
||||||
unsigned short flags, int kind)
|
|
||||||
{
|
{
|
||||||
/* Define needed variables */
|
(...)
|
||||||
|
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||||
/* As the very first action, we check whether the adapter has the
|
I2C_FUNC_SMBUS_WORD_DATA))
|
||||||
needed functionality: we need the SMBus read_word_data,
|
goto exit;
|
||||||
write_word_data and write_byte functions in this example. */
|
(...)
|
||||||
if (!i2c_check_functionality(adapter,I2C_FUNC_SMBUS_WORD_DATA |
|
|
||||||
I2C_FUNC_SMBUS_WRITE_BYTE))
|
|
||||||
goto ERROR0;
|
|
||||||
|
|
||||||
/* Now we can do the real detection */
|
|
||||||
|
|
||||||
ERROR0:
|
|
||||||
/* Return an error */
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Here, the lm75 driver checks if the adapter can do both SMBus byte data
|
||||||
|
and SMBus word data transactions. If not, then the driver won't work on
|
||||||
|
this adapter and there's no point in going on. If the check above is
|
||||||
|
successful, then the driver knows that it can call the following
|
||||||
|
functions: i2c_smbus_read_byte_data(), i2c_smbus_write_byte_data(),
|
||||||
|
i2c_smbus_read_word_data() and i2c_smbus_write_word_data(). As a rule of
|
||||||
|
thumb, the functionality constants you test for with
|
||||||
|
i2c_check_functionality() should match exactly the i2c_smbus_* functions
|
||||||
|
which you driver is calling.
|
||||||
|
|
||||||
|
Note that the check above doesn't tell whether the functionalities are
|
||||||
|
implemented in hardware by the underlying adapter or emulated in
|
||||||
|
software by i2c-core. Client drivers don't have to care about this, as
|
||||||
|
i2c-core will transparently implement SMBus transactions on top of I2C
|
||||||
|
adapters.
|
||||||
|
|
||||||
|
|
||||||
CHECKING THROUGH /DEV
|
CHECKING THROUGH /DEV
|
||||||
|
@ -116,19 +125,19 @@ CHECKING THROUGH /DEV
|
||||||
If you try to access an adapter from a userspace program, you will have
|
If you try to access an adapter from a userspace program, you will have
|
||||||
to use the /dev interface. You will still have to check whether the
|
to use the /dev interface. You will still have to check whether the
|
||||||
functionality you need is supported, of course. This is done using
|
functionality you need is supported, of course. This is done using
|
||||||
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
|
the I2C_FUNCS ioctl. An example, adapted from the i2cdetect program, is
|
||||||
program, is below:
|
below:
|
||||||
|
|
||||||
int file;
|
int file;
|
||||||
if (file = open("/dev/i2c-0",O_RDWR) < 0) {
|
if (file = open("/dev/i2c-0", O_RDWR) < 0) {
|
||||||
/* Some kind of error handling */
|
/* Some kind of error handling */
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
|
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||||
/* Some kind of error handling */
|
/* Some kind of error handling */
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
if (! (funcs & I2C_FUNC_SMBUS_QUICK)) {
|
if (!(funcs & I2C_FUNC_SMBUS_QUICK)) {
|
||||||
/* Oops, the needed functionality (SMBus write_quick function) is
|
/* Oops, the needed functionality (SMBus write_quick function) is
|
||||||
not available! */
|
not available! */
|
||||||
exit(1);
|
exit(1);
|
||||||
|
|
|
@ -1,5 +1,6 @@
|
||||||
SMBus Protocol Summary
|
SMBus Protocol Summary
|
||||||
======================
|
======================
|
||||||
|
|
||||||
The following is a summary of the SMBus protocol. It applies to
|
The following is a summary of the SMBus protocol. It applies to
|
||||||
all revisions of the protocol (1.0, 1.1, and 2.0).
|
all revisions of the protocol (1.0, 1.1, and 2.0).
|
||||||
Certain protocol features which are not supported by
|
Certain protocol features which are not supported by
|
||||||
|
@ -8,6 +9,7 @@ this package are briefly described at the end of this document.
|
||||||
Some adapters understand only the SMBus (System Management Bus) protocol,
|
Some adapters understand only the SMBus (System Management Bus) protocol,
|
||||||
which is a subset from the I2C protocol. Fortunately, many devices use
|
which is a subset from the I2C protocol. Fortunately, many devices use
|
||||||
only the same subset, which makes it possible to put them on an SMBus.
|
only the same subset, which makes it possible to put them on an SMBus.
|
||||||
|
|
||||||
If you write a driver for some I2C device, please try to use the SMBus
|
If you write a driver for some I2C device, please try to use the SMBus
|
||||||
commands if at all possible (if the device uses only that subset of the
|
commands if at all possible (if the device uses only that subset of the
|
||||||
I2C protocol). This makes it possible to use the device driver on both
|
I2C protocol). This makes it possible to use the device driver on both
|
||||||
|
@ -15,7 +17,12 @@ SMBus adapters and I2C adapters (the SMBus command set is automatically
|
||||||
translated to I2C on I2C adapters, but plain I2C commands can not be
|
translated to I2C on I2C adapters, but plain I2C commands can not be
|
||||||
handled at all on most pure SMBus adapters).
|
handled at all on most pure SMBus adapters).
|
||||||
|
|
||||||
Below is a list of SMBus commands.
|
Below is a list of SMBus protocol operations, and the functions executing
|
||||||
|
them. Note that the names used in the SMBus protocol specifications usually
|
||||||
|
don't match these function names. For some of the operations which pass a
|
||||||
|
single data byte, the functions using SMBus protocol operation names execute
|
||||||
|
a different protocol operation entirely.
|
||||||
|
|
||||||
|
|
||||||
Key to symbols
|
Key to symbols
|
||||||
==============
|
==============
|
||||||
|
@ -35,17 +42,16 @@ Count (8 bits): A data byte containing the length of a block operation.
|
||||||
[..]: Data sent by I2C device, as opposed to data sent by the host adapter.
|
[..]: Data sent by I2C device, as opposed to data sent by the host adapter.
|
||||||
|
|
||||||
|
|
||||||
SMBus Write Quick
|
SMBus Quick Command: i2c_smbus_write_quick()
|
||||||
=================
|
=============================================
|
||||||
|
|
||||||
This sends a single bit to the device, at the place of the Rd/Wr bit.
|
This sends a single bit to the device, at the place of the Rd/Wr bit.
|
||||||
There is no equivalent Read Quick command.
|
|
||||||
|
|
||||||
A Addr Rd/Wr [A] P
|
A Addr Rd/Wr [A] P
|
||||||
|
|
||||||
|
|
||||||
SMBus Read Byte
|
SMBus Receive Byte: i2c_smbus_read_byte()
|
||||||
===============
|
==========================================
|
||||||
|
|
||||||
This reads a single byte from a device, without specifying a device
|
This reads a single byte from a device, without specifying a device
|
||||||
register. Some devices are so simple that this interface is enough; for
|
register. Some devices are so simple that this interface is enough; for
|
||||||
|
@ -55,17 +61,17 @@ the previous SMBus command.
|
||||||
S Addr Rd [A] [Data] NA P
|
S Addr Rd [A] [Data] NA P
|
||||||
|
|
||||||
|
|
||||||
SMBus Write Byte
|
SMBus Send Byte: i2c_smbus_write_byte()
|
||||||
================
|
========================================
|
||||||
|
|
||||||
This is the reverse of Read Byte: it sends a single byte to a device.
|
This operation is the reverse of Receive Byte: it sends a single byte
|
||||||
See Read Byte for more information.
|
to a device. See Receive Byte for more information.
|
||||||
|
|
||||||
S Addr Wr [A] Data [A] P
|
S Addr Wr [A] Data [A] P
|
||||||
|
|
||||||
|
|
||||||
SMBus Read Byte Data
|
SMBus Read Byte: i2c_smbus_read_byte_data()
|
||||||
====================
|
============================================
|
||||||
|
|
||||||
This reads a single byte from a device, from a designated register.
|
This reads a single byte from a device, from a designated register.
|
||||||
The register is specified through the Comm byte.
|
The register is specified through the Comm byte.
|
||||||
|
@ -73,30 +79,30 @@ The register is specified through the Comm byte.
|
||||||
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
|
S Addr Wr [A] Comm [A] S Addr Rd [A] [Data] NA P
|
||||||
|
|
||||||
|
|
||||||
SMBus Read Word Data
|
SMBus Read Word: i2c_smbus_read_word_data()
|
||||||
====================
|
============================================
|
||||||
|
|
||||||
This command is very like Read Byte Data; again, data is read from a
|
This operation is very like Read Byte; again, data is read from a
|
||||||
device, from a designated register that is specified through the Comm
|
device, from a designated register that is specified through the Comm
|
||||||
byte. But this time, the data is a complete word (16 bits).
|
byte. But this time, the data is a complete word (16 bits).
|
||||||
|
|
||||||
S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
|
S Addr Wr [A] Comm [A] S Addr Rd [A] [DataLow] A [DataHigh] NA P
|
||||||
|
|
||||||
|
|
||||||
SMBus Write Byte Data
|
SMBus Write Byte: i2c_smbus_write_byte_data()
|
||||||
=====================
|
==============================================
|
||||||
|
|
||||||
This writes a single byte to a device, to a designated register. The
|
This writes a single byte to a device, to a designated register. The
|
||||||
register is specified through the Comm byte. This is the opposite of
|
register is specified through the Comm byte. This is the opposite of
|
||||||
the Read Byte Data command.
|
the Read Byte operation.
|
||||||
|
|
||||||
S Addr Wr [A] Comm [A] Data [A] P
|
S Addr Wr [A] Comm [A] Data [A] P
|
||||||
|
|
||||||
|
|
||||||
SMBus Write Word Data
|
SMBus Write Word: i2c_smbus_write_word_data()
|
||||||
=====================
|
==============================================
|
||||||
|
|
||||||
This is the opposite operation of the Read Word Data command. 16 bits
|
This is the opposite of the Read Word operation. 16 bits
|
||||||
of data is written to a device, to the designated register that is
|
of data is written to a device, to the designated register that is
|
||||||
specified through the Comm byte.
|
specified through the Comm byte.
|
||||||
|
|
||||||
|
@ -113,8 +119,8 @@ S Addr Wr [A] Comm [A] DataLow [A] DataHigh [A]
|
||||||
S Addr Rd [A] [DataLow] A [DataHigh] NA P
|
S Addr Rd [A] [DataLow] A [DataHigh] NA P
|
||||||
|
|
||||||
|
|
||||||
SMBus Block Read
|
SMBus Block Read: i2c_smbus_read_block_data()
|
||||||
================
|
==============================================
|
||||||
|
|
||||||
This command reads a block of up to 32 bytes from a device, from a
|
This command reads a block of up to 32 bytes from a device, from a
|
||||||
designated register that is specified through the Comm byte. The amount
|
designated register that is specified through the Comm byte. The amount
|
||||||
|
@ -124,8 +130,8 @@ S Addr Wr [A] Comm [A]
|
||||||
S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
|
S Addr Rd [A] [Count] A [Data] A [Data] A ... A [Data] NA P
|
||||||
|
|
||||||
|
|
||||||
SMBus Block Write
|
SMBus Block Write: i2c_smbus_write_block_data()
|
||||||
=================
|
================================================
|
||||||
|
|
||||||
The opposite of the Block Read command, this writes up to 32 bytes to
|
The opposite of the Block Read command, this writes up to 32 bytes to
|
||||||
a device, to a designated register that is specified through the
|
a device, to a designated register that is specified through the
|
||||||
|
@ -134,10 +140,11 @@ Comm byte. The amount of data is specified in the Count byte.
|
||||||
S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
|
S Addr Wr [A] Comm [A] Count [A] Data [A] Data [A] ... [A] Data [A] P
|
||||||
|
|
||||||
|
|
||||||
SMBus Block Process Call
|
SMBus Block Write - Block Read Process Call
|
||||||
========================
|
===========================================
|
||||||
|
|
||||||
SMBus Block Process Call was introduced in Revision 2.0 of the specification.
|
SMBus Block Write - Block Read Process Call was introduced in
|
||||||
|
Revision 2.0 of the specification.
|
||||||
|
|
||||||
This command selects a device register (through the Comm byte), sends
|
This command selects a device register (through the Comm byte), sends
|
||||||
1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return.
|
1 to 31 bytes of data to it, and reads 1 to 31 bytes of data in return.
|
||||||
|
@ -159,13 +166,16 @@ alerting device's address.
|
||||||
|
|
||||||
Packet Error Checking (PEC)
|
Packet Error Checking (PEC)
|
||||||
===========================
|
===========================
|
||||||
|
|
||||||
Packet Error Checking was introduced in Revision 1.1 of the specification.
|
Packet Error Checking was introduced in Revision 1.1 of the specification.
|
||||||
|
|
||||||
PEC adds a CRC-8 error-checking byte to all transfers.
|
PEC adds a CRC-8 error-checking byte to transfers using it, immediately
|
||||||
|
before the terminating STOP.
|
||||||
|
|
||||||
|
|
||||||
Address Resolution Protocol (ARP)
|
Address Resolution Protocol (ARP)
|
||||||
=================================
|
=================================
|
||||||
|
|
||||||
The Address Resolution Protocol was introduced in Revision 2.0 of
|
The Address Resolution Protocol was introduced in Revision 2.0 of
|
||||||
the specification. It is a higher-layer protocol which uses the
|
the specification. It is a higher-layer protocol which uses the
|
||||||
messages above.
|
messages above.
|
||||||
|
@ -177,14 +187,17 @@ require PEC checksums.
|
||||||
|
|
||||||
I2C Block Transactions
|
I2C Block Transactions
|
||||||
======================
|
======================
|
||||||
|
|
||||||
The following I2C block transactions are supported by the
|
The following I2C block transactions are supported by the
|
||||||
SMBus layer and are described here for completeness.
|
SMBus layer and are described here for completeness.
|
||||||
|
They are *NOT* defined by the SMBus specification.
|
||||||
|
|
||||||
I2C block transactions do not limit the number of bytes transferred
|
I2C block transactions do not limit the number of bytes transferred
|
||||||
but the SMBus layer places a limit of 32 bytes.
|
but the SMBus layer places a limit of 32 bytes.
|
||||||
|
|
||||||
|
|
||||||
I2C Block Read
|
I2C Block Read: i2c_smbus_read_i2c_block_data()
|
||||||
==============
|
================================================
|
||||||
|
|
||||||
This command reads a block of bytes from a device, from a
|
This command reads a block of bytes from a device, from a
|
||||||
designated register that is specified through the Comm byte.
|
designated register that is specified through the Comm byte.
|
||||||
|
@ -203,8 +216,8 @@ S Addr Wr [A] Comm1 [A] Comm2 [A]
|
||||||
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
|
S Addr Rd [A] [Data] A [Data] A ... A [Data] NA P
|
||||||
|
|
||||||
|
|
||||||
I2C Block Write
|
I2C Block Write: i2c_smbus_write_i2c_block_data()
|
||||||
===============
|
==================================================
|
||||||
|
|
||||||
The opposite of the Block Read command, this writes bytes to
|
The opposite of the Block Read command, this writes bytes to
|
||||||
a device, to a designated register that is specified through the
|
a device, to a designated register that is specified through the
|
||||||
|
@ -212,5 +225,3 @@ Comm byte. Note that command lengths of 0, 2, or more bytes are
|
||||||
supported as they are indistinguishable from data.
|
supported as they are indistinguishable from data.
|
||||||
|
|
||||||
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
|
S Addr Wr [A] Comm [A] Data [A] Data [A] ... [A] Data [A] P
|
||||||
|
|
||||||
|
|
||||||
|
|
|
@ -99,7 +99,7 @@ static int i2c_wait(struct mpc_i2c *i2c, unsigned timeout, int writing)
|
||||||
u32 x;
|
u32 x;
|
||||||
int result = 0;
|
int result = 0;
|
||||||
|
|
||||||
if (i2c->irq == 0)
|
if (i2c->irq == NO_IRQ)
|
||||||
{
|
{
|
||||||
while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
|
while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
|
||||||
schedule();
|
schedule();
|
||||||
|
@ -329,10 +329,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
|
||||||
return -ENOMEM;
|
return -ENOMEM;
|
||||||
|
|
||||||
i2c->irq = platform_get_irq(pdev, 0);
|
i2c->irq = platform_get_irq(pdev, 0);
|
||||||
if (i2c->irq < 0) {
|
if (i2c->irq < 0)
|
||||||
result = -ENXIO;
|
i2c->irq = NO_IRQ; /* Use polling */
|
||||||
goto fail_get_irq;
|
|
||||||
}
|
|
||||||
i2c->flags = pdata->device_flags;
|
i2c->flags = pdata->device_flags;
|
||||||
init_waitqueue_head(&i2c->queue);
|
init_waitqueue_head(&i2c->queue);
|
||||||
|
|
||||||
|
@ -344,7 +343,7 @@ static int fsl_i2c_probe(struct platform_device *pdev)
|
||||||
goto fail_map;
|
goto fail_map;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (i2c->irq != 0)
|
if (i2c->irq != NO_IRQ)
|
||||||
if ((result = request_irq(i2c->irq, mpc_i2c_isr,
|
if ((result = request_irq(i2c->irq, mpc_i2c_isr,
|
||||||
IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
|
IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
|
||||||
printk(KERN_ERR
|
printk(KERN_ERR
|
||||||
|
@ -367,12 +366,11 @@ static int fsl_i2c_probe(struct platform_device *pdev)
|
||||||
return result;
|
return result;
|
||||||
|
|
||||||
fail_add:
|
fail_add:
|
||||||
if (i2c->irq != 0)
|
if (i2c->irq != NO_IRQ)
|
||||||
free_irq(i2c->irq, i2c);
|
free_irq(i2c->irq, i2c);
|
||||||
fail_irq:
|
fail_irq:
|
||||||
iounmap(i2c->base);
|
iounmap(i2c->base);
|
||||||
fail_map:
|
fail_map:
|
||||||
fail_get_irq:
|
|
||||||
kfree(i2c);
|
kfree(i2c);
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
@ -384,7 +382,7 @@ static int fsl_i2c_remove(struct platform_device *pdev)
|
||||||
i2c_del_adapter(&i2c->adap);
|
i2c_del_adapter(&i2c->adap);
|
||||||
platform_set_drvdata(pdev, NULL);
|
platform_set_drvdata(pdev, NULL);
|
||||||
|
|
||||||
if (i2c->irq != 0)
|
if (i2c->irq != NO_IRQ)
|
||||||
free_irq(i2c->irq, i2c);
|
free_irq(i2c->irq, i2c);
|
||||||
|
|
||||||
iounmap(i2c->base);
|
iounmap(i2c->base);
|
||||||
|
|
|
@ -104,10 +104,31 @@ MODULE_PARM_DESC(force_addr,
|
||||||
static int piix4_transaction(void);
|
static int piix4_transaction(void);
|
||||||
|
|
||||||
static unsigned short piix4_smba;
|
static unsigned short piix4_smba;
|
||||||
|
static int srvrworks_csb5_delay;
|
||||||
static struct pci_driver piix4_driver;
|
static struct pci_driver piix4_driver;
|
||||||
static struct i2c_adapter piix4_adapter;
|
static struct i2c_adapter piix4_adapter;
|
||||||
|
|
||||||
static struct dmi_system_id __devinitdata piix4_dmi_table[] = {
|
static struct dmi_system_id __devinitdata piix4_dmi_blacklist[] = {
|
||||||
|
{
|
||||||
|
.ident = "Sapphire AM2RD790",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "SAPPHIRE Inc."),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "PC-AM2RD790"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{
|
||||||
|
.ident = "DFI Lanparty UT 790FX",
|
||||||
|
.matches = {
|
||||||
|
DMI_MATCH(DMI_BOARD_VENDOR, "DFI Inc."),
|
||||||
|
DMI_MATCH(DMI_BOARD_NAME, "LP UT 790FX"),
|
||||||
|
},
|
||||||
|
},
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
|
||||||
|
/* The IBM entry is in a separate table because we only check it
|
||||||
|
on Intel-based systems */
|
||||||
|
static struct dmi_system_id __devinitdata piix4_dmi_ibm[] = {
|
||||||
{
|
{
|
||||||
.ident = "IBM",
|
.ident = "IBM",
|
||||||
.matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
|
.matches = { DMI_MATCH(DMI_SYS_VENDOR, "IBM"), },
|
||||||
|
@ -122,8 +143,20 @@ static int __devinit piix4_setup(struct pci_dev *PIIX4_dev,
|
||||||
|
|
||||||
dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
|
dev_info(&PIIX4_dev->dev, "Found %s device\n", pci_name(PIIX4_dev));
|
||||||
|
|
||||||
|
if ((PIIX4_dev->vendor == PCI_VENDOR_ID_SERVERWORKS) &&
|
||||||
|
(PIIX4_dev->device == PCI_DEVICE_ID_SERVERWORKS_CSB5))
|
||||||
|
srvrworks_csb5_delay = 1;
|
||||||
|
|
||||||
|
/* On some motherboards, it was reported that accessing the SMBus
|
||||||
|
caused severe hardware problems */
|
||||||
|
if (dmi_check_system(piix4_dmi_blacklist)) {
|
||||||
|
dev_err(&PIIX4_dev->dev,
|
||||||
|
"Accessing the SMBus on this system is unsafe!\n");
|
||||||
|
return -EPERM;
|
||||||
|
}
|
||||||
|
|
||||||
/* Don't access SMBus on IBM systems which get corrupted eeproms */
|
/* Don't access SMBus on IBM systems which get corrupted eeproms */
|
||||||
if (dmi_check_system(piix4_dmi_table) &&
|
if (dmi_check_system(piix4_dmi_ibm) &&
|
||||||
PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
|
PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
|
||||||
dev_err(&PIIX4_dev->dev, "IBM system detected; this module "
|
dev_err(&PIIX4_dev->dev, "IBM system detected; this module "
|
||||||
"may corrupt your serial eeprom! Refusing to load "
|
"may corrupt your serial eeprom! Refusing to load "
|
||||||
|
@ -230,10 +263,14 @@ static int piix4_transaction(void)
|
||||||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||||
|
|
||||||
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
|
/* We will always wait for a fraction of a second! (See PIIX4 docs errata) */
|
||||||
do {
|
if (srvrworks_csb5_delay) /* Extra delay for SERVERWORKS_CSB5 */
|
||||||
|
msleep(2);
|
||||||
|
else
|
||||||
|
msleep(1);
|
||||||
|
|
||||||
|
while ((timeout++ < MAX_TIMEOUT) &&
|
||||||
|
((temp = inb_p(SMBHSTSTS)) & 0x01))
|
||||||
msleep(1);
|
msleep(1);
|
||||||
temp = inb_p(SMBHSTSTS);
|
|
||||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
|
||||||
|
|
||||||
/* If the SMBus is still busy, we give up */
|
/* If the SMBus is still busy, we give up */
|
||||||
if (timeout >= MAX_TIMEOUT) {
|
if (timeout >= MAX_TIMEOUT) {
|
||||||
|
|
|
@ -132,14 +132,14 @@ static const struct i2c_algorithm i2c_sibyte_algo = {
|
||||||
/*
|
/*
|
||||||
* registering functions to load algorithms at runtime
|
* registering functions to load algorithms at runtime
|
||||||
*/
|
*/
|
||||||
int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
|
static int __init i2c_sibyte_add_bus(struct i2c_adapter *i2c_adap, int speed)
|
||||||
{
|
{
|
||||||
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
|
struct i2c_algo_sibyte_data *adap = i2c_adap->algo_data;
|
||||||
|
|
||||||
/* register new adapter to i2c module... */
|
/* Register new adapter to i2c module... */
|
||||||
i2c_adap->algo = &i2c_sibyte_algo;
|
i2c_adap->algo = &i2c_sibyte_algo;
|
||||||
|
|
||||||
/* Set the frequency to 100 kHz */
|
/* Set the requested frequency. */
|
||||||
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
|
csr_out32(speed, SMB_CSR(adap,R_SMB_FREQ));
|
||||||
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
|
csr_out32(0, SMB_CSR(adap,R_SMB_CONTROL));
|
||||||
|
|
||||||
|
|
|
@ -327,6 +327,11 @@ void i2c_unregister_device(struct i2c_client *client)
|
||||||
EXPORT_SYMBOL_GPL(i2c_unregister_device);
|
EXPORT_SYMBOL_GPL(i2c_unregister_device);
|
||||||
|
|
||||||
|
|
||||||
|
static const struct i2c_device_id dummy_id[] = {
|
||||||
|
{ "dummy", 0 },
|
||||||
|
{ },
|
||||||
|
};
|
||||||
|
|
||||||
static int dummy_probe(struct i2c_client *client,
|
static int dummy_probe(struct i2c_client *client,
|
||||||
const struct i2c_device_id *id)
|
const struct i2c_device_id *id)
|
||||||
{
|
{
|
||||||
|
@ -342,13 +347,13 @@ static struct i2c_driver dummy_driver = {
|
||||||
.driver.name = "dummy",
|
.driver.name = "dummy",
|
||||||
.probe = dummy_probe,
|
.probe = dummy_probe,
|
||||||
.remove = dummy_remove,
|
.remove = dummy_remove,
|
||||||
|
.id_table = dummy_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* i2c_new_dummy - return a new i2c device bound to a dummy driver
|
* i2c_new_dummy - return a new i2c device bound to a dummy driver
|
||||||
* @adapter: the adapter managing the device
|
* @adapter: the adapter managing the device
|
||||||
* @address: seven bit address to be used
|
* @address: seven bit address to be used
|
||||||
* @type: optional label used for i2c_client.name
|
|
||||||
* Context: can sleep
|
* Context: can sleep
|
||||||
*
|
*
|
||||||
* This returns an I2C client bound to the "dummy" driver, intended for use
|
* This returns an I2C client bound to the "dummy" driver, intended for use
|
||||||
|
@ -364,15 +369,12 @@ static struct i2c_driver dummy_driver = {
|
||||||
* i2c_unregister_device(); or NULL to indicate an error.
|
* i2c_unregister_device(); or NULL to indicate an error.
|
||||||
*/
|
*/
|
||||||
struct i2c_client *
|
struct i2c_client *
|
||||||
i2c_new_dummy(struct i2c_adapter *adapter, u16 address, const char *type)
|
i2c_new_dummy(struct i2c_adapter *adapter, u16 address)
|
||||||
{
|
{
|
||||||
struct i2c_board_info info = {
|
struct i2c_board_info info = {
|
||||||
.driver_name = "dummy",
|
I2C_BOARD_INFO("dummy", address),
|
||||||
.addr = address,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
if (type)
|
|
||||||
strlcpy(info.type, type, sizeof info.type);
|
|
||||||
return i2c_new_device(adapter, &info);
|
return i2c_new_device(adapter, &info);
|
||||||
}
|
}
|
||||||
EXPORT_SYMBOL_GPL(i2c_new_dummy);
|
EXPORT_SYMBOL_GPL(i2c_new_dummy);
|
||||||
|
|
|
@ -885,12 +885,19 @@ static int __exit tcm825x_remove(struct i2c_client *client)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static const struct i2c_device_id tcm825x_id[] = {
|
||||||
|
{ "tcm825x", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, tcm825x_id);
|
||||||
|
|
||||||
static struct i2c_driver tcm825x_i2c_driver = {
|
static struct i2c_driver tcm825x_i2c_driver = {
|
||||||
.driver = {
|
.driver = {
|
||||||
.name = TCM825X_NAME,
|
.name = TCM825X_NAME,
|
||||||
},
|
},
|
||||||
.probe = tcm825x_probe,
|
.probe = tcm825x_probe,
|
||||||
.remove = __exit_p(tcm825x_remove),
|
.remove = __exit_p(tcm825x_remove),
|
||||||
|
.id_table = tcm825x_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct tcm825x_sensor tcm825x = {
|
static struct tcm825x_sensor tcm825x = {
|
||||||
|
|
|
@ -168,6 +168,11 @@ static int tlv320aic23b_remove(struct i2c_client *client)
|
||||||
|
|
||||||
/* ----------------------------------------------------------------------- */
|
/* ----------------------------------------------------------------------- */
|
||||||
|
|
||||||
|
static const struct i2c_device_id tlv320aic23b_id[] = {
|
||||||
|
{ "tlv320aic23b", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, tlv320aic23b_id);
|
||||||
|
|
||||||
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
||||||
.name = "tlv320aic23b",
|
.name = "tlv320aic23b",
|
||||||
|
@ -175,4 +180,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
||||||
.command = tlv320aic23b_command,
|
.command = tlv320aic23b_command,
|
||||||
.probe = tlv320aic23b_probe,
|
.probe = tlv320aic23b_probe,
|
||||||
.remove = tlv320aic23b_remove,
|
.remove = tlv320aic23b_remove,
|
||||||
|
.id_table = tlv320aic23b_id,
|
||||||
};
|
};
|
||||||
|
|
|
@ -1505,7 +1505,8 @@ static int chip_probe(struct i2c_client *client, const struct i2c_device_id *id)
|
||||||
}
|
}
|
||||||
|
|
||||||
/* fill required data structures */
|
/* fill required data structures */
|
||||||
strcpy(client->name, desc->name);
|
if (!id)
|
||||||
|
strlcpy(client->name, desc->name, I2C_NAME_SIZE);
|
||||||
chip->type = desc-chiplist;
|
chip->type = desc-chiplist;
|
||||||
chip->shadow.count = desc->registers+1;
|
chip->shadow.count = desc->registers+1;
|
||||||
chip->prevmode = -1;
|
chip->prevmode = -1;
|
||||||
|
@ -1830,6 +1831,15 @@ static int chip_legacy_probe(struct i2c_adapter *adap)
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* This driver supports many devices and the idea is to let the driver
|
||||||
|
detect which device is present. So rather than listing all supported
|
||||||
|
devices here, we pretend to support a single, fake device type. */
|
||||||
|
static const struct i2c_device_id chip_id[] = {
|
||||||
|
{ "tvaudio", 0 },
|
||||||
|
{ }
|
||||||
|
};
|
||||||
|
MODULE_DEVICE_TABLE(i2c, chip_id);
|
||||||
|
|
||||||
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
||||||
.name = "tvaudio",
|
.name = "tvaudio",
|
||||||
.driverid = I2C_DRIVERID_TVAUDIO,
|
.driverid = I2C_DRIVERID_TVAUDIO,
|
||||||
|
@ -1837,6 +1847,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
||||||
.probe = chip_probe,
|
.probe = chip_probe,
|
||||||
.remove = chip_remove,
|
.remove = chip_remove,
|
||||||
.legacy_probe = chip_legacy_probe,
|
.legacy_probe = chip_legacy_probe,
|
||||||
|
.id_table = chip_id,
|
||||||
};
|
};
|
||||||
|
|
||||||
/*
|
/*
|
||||||
|
|
|
@ -227,7 +227,7 @@ static int s35390a_probe(struct i2c_client *client,
|
||||||
/* This chip uses multiple addresses, use dummy devices for them */
|
/* This chip uses multiple addresses, use dummy devices for them */
|
||||||
for (i = 1; i < 8; ++i) {
|
for (i = 1; i < 8; ++i) {
|
||||||
s35390a->client[i] = i2c_new_dummy(client->adapter,
|
s35390a->client[i] = i2c_new_dummy(client->adapter,
|
||||||
client->addr + i, "rtc-s35390a");
|
client->addr + i);
|
||||||
if (!s35390a->client[i]) {
|
if (!s35390a->client[i]) {
|
||||||
dev_err(&client->dev, "Address %02x unavailable\n",
|
dev_err(&client->dev, "Address %02x unavailable\n",
|
||||||
client->addr + i);
|
client->addr + i);
|
||||||
|
|
|
@ -262,7 +262,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,
|
||||||
* client handles for the extra addresses.
|
* client handles for the extra addresses.
|
||||||
*/
|
*/
|
||||||
extern struct i2c_client *
|
extern struct i2c_client *
|
||||||
i2c_new_dummy(struct i2c_adapter *adap, u16 address, const char *type);
|
i2c_new_dummy(struct i2c_adapter *adap, u16 address);
|
||||||
|
|
||||||
extern void i2c_unregister_device(struct i2c_client *);
|
extern void i2c_unregister_device(struct i2c_client *);
|
||||||
|
|
||||||
|
|
|
@ -31,6 +31,7 @@ struct v4l2_i2c_driver_data {
|
||||||
int (*resume)(struct i2c_client *client);
|
int (*resume)(struct i2c_client *client);
|
||||||
int (*legacy_probe)(struct i2c_adapter *adapter);
|
int (*legacy_probe)(struct i2c_adapter *adapter);
|
||||||
int legacy_class;
|
int legacy_class;
|
||||||
|
const struct i2c_device_id *id_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_i2c_driver_data v4l2_i2c_data;
|
static struct v4l2_i2c_driver_data v4l2_i2c_data;
|
||||||
|
@ -124,6 +125,7 @@ static int __init v4l2_i2c_drv_init(void)
|
||||||
v4l2_i2c_driver.command = v4l2_i2c_data.command;
|
v4l2_i2c_driver.command = v4l2_i2c_data.command;
|
||||||
v4l2_i2c_driver.probe = v4l2_i2c_data.probe;
|
v4l2_i2c_driver.probe = v4l2_i2c_data.probe;
|
||||||
v4l2_i2c_driver.remove = v4l2_i2c_data.remove;
|
v4l2_i2c_driver.remove = v4l2_i2c_data.remove;
|
||||||
|
v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table;
|
||||||
err = i2c_add_driver(&v4l2_i2c_driver);
|
err = i2c_add_driver(&v4l2_i2c_driver);
|
||||||
if (err)
|
if (err)
|
||||||
i2c_del_driver(&v4l2_i2c_driver_legacy);
|
i2c_del_driver(&v4l2_i2c_driver_legacy);
|
||||||
|
|
|
@ -36,6 +36,7 @@ struct v4l2_i2c_driver_data {
|
||||||
int (*resume)(struct i2c_client *client);
|
int (*resume)(struct i2c_client *client);
|
||||||
int (*legacy_probe)(struct i2c_adapter *adapter);
|
int (*legacy_probe)(struct i2c_adapter *adapter);
|
||||||
int legacy_class;
|
int legacy_class;
|
||||||
|
const struct i2c_device_id *id_table;
|
||||||
};
|
};
|
||||||
|
|
||||||
static struct v4l2_i2c_driver_data v4l2_i2c_data;
|
static struct v4l2_i2c_driver_data v4l2_i2c_data;
|
||||||
|
@ -53,6 +54,7 @@ static int __init v4l2_i2c_drv_init(void)
|
||||||
v4l2_i2c_driver.remove = v4l2_i2c_data.remove;
|
v4l2_i2c_driver.remove = v4l2_i2c_data.remove;
|
||||||
v4l2_i2c_driver.suspend = v4l2_i2c_data.suspend;
|
v4l2_i2c_driver.suspend = v4l2_i2c_data.suspend;
|
||||||
v4l2_i2c_driver.resume = v4l2_i2c_data.resume;
|
v4l2_i2c_driver.resume = v4l2_i2c_data.resume;
|
||||||
|
v4l2_i2c_driver.id_table = v4l2_i2c_data.id_table;
|
||||||
return i2c_add_driver(&v4l2_i2c_driver);
|
return i2c_add_driver(&v4l2_i2c_driver);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue