mirror of
https://github.com/adulau/aha.git
synced 2024-12-28 11:46:19 +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)
|
||||
|
||||
|
||||
ALGORITHM/ADAPTER IMPLEMENTATION
|
||||
--------------------------------
|
||||
ADAPTER IMPLEMENTATION
|
||||
----------------------
|
||||
|
||||
When you write a new algorithm driver, you will have to implement a
|
||||
function callback `functionality', that gets an i2c_adapter structure
|
||||
pointer as its only parameter:
|
||||
When you write a new adapter driver, you will have to implement a
|
||||
function callback `functionality'. Typical implementations are given
|
||||
below.
|
||||
|
||||
struct i2c_algorithm {
|
||||
/* Many other things of course; check <linux/i2c.h>! */
|
||||
u32 (*functionality) (struct i2c_adapter *);
|
||||
}
|
||||
A typical SMBus-only adapter would list all the SMBus transactions it
|
||||
supports. This example comes from the i2c-piix4 driver:
|
||||
|
||||
A typically implementation is given below, from i2c-algo-bit.c:
|
||||
|
||||
static u32 bit_func(struct i2c_adapter *adap)
|
||||
static u32 piix4_func(struct i2c_adapter *adapter)
|
||||
{
|
||||
return I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR |
|
||||
I2C_FUNC_PROTOCOL_MANGLING;
|
||||
return I2C_FUNC_SMBUS_QUICK | I2C_FUNC_SMBUS_BYTE |
|
||||
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
|
||||
|
@ -78,36 +90,33 @@ CLIENT CHECKING
|
|||
|
||||
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
|
||||
check whether the needed functionality is present. There are two functions
|
||||
defined which should be used instead of calling the functionality hook
|
||||
in the algorithm structure directly:
|
||||
check whether the needed functionality is present. The typical way to do
|
||||
this is (from the lm75 driver):
|
||||
|
||||
/* Return the functionality mask */
|
||||
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)
|
||||
static int lm75_detect(...)
|
||||
{
|
||||
/* Define needed variables */
|
||||
|
||||
/* As the very first action, we check whether the adapter has the
|
||||
needed functionality: we need the SMBus read_word_data,
|
||||
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 */
|
||||
(...)
|
||||
if (!i2c_check_functionality(adapter, I2C_FUNC_SMBUS_BYTE_DATA |
|
||||
I2C_FUNC_SMBUS_WORD_DATA))
|
||||
goto exit;
|
||||
(...)
|
||||
}
|
||||
|
||||
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
|
||||
|
@ -116,19 +125,19 @@ CHECKING THROUGH /DEV
|
|||
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
|
||||
functionality you need is supported, of course. This is done using
|
||||
the I2C_FUNCS ioctl. An example, adapted from the lm_sensors i2cdetect
|
||||
program, is below:
|
||||
the I2C_FUNCS ioctl. An example, adapted from the i2cdetect program, is
|
||||
below:
|
||||
|
||||
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 */
|
||||
exit(1);
|
||||
}
|
||||
if (ioctl(file,I2C_FUNCS,&funcs) < 0) {
|
||||
if (ioctl(file, I2C_FUNCS, &funcs) < 0) {
|
||||
/* Some kind of error handling */
|
||||
exit(1);
|
||||
}
|
||||
if (! (funcs & I2C_FUNC_SMBUS_QUICK)) {
|
||||
if (!(funcs & I2C_FUNC_SMBUS_QUICK)) {
|
||||
/* Oops, the needed functionality (SMBus write_quick function) is
|
||||
not available! */
|
||||
exit(1);
|
||||
|
|
|
@ -1,5 +1,6 @@
|
|||
SMBus Protocol Summary
|
||||
======================
|
||||
|
||||
The following is a summary of the SMBus protocol. It applies to
|
||||
all revisions of the protocol (1.0, 1.1, and 2.0).
|
||||
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,
|
||||
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.
|
||||
|
||||
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
|
||||
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
|
||||
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
|
||||
==============
|
||||
|
@ -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.
|
||||
|
||||
|
||||
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.
|
||||
There is no equivalent Read Quick command.
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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.
|
||||
See Read Byte for more information.
|
||||
This operation is the reverse of Receive Byte: it sends a single byte
|
||||
to a device. See Receive Byte for more information.
|
||||
|
||||
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.
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
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
|
||||
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 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)
|
||||
=================================
|
||||
|
||||
The Address Resolution Protocol was introduced in Revision 2.0 of
|
||||
the specification. It is a higher-layer protocol which uses the
|
||||
messages above.
|
||||
|
@ -177,14 +187,17 @@ require PEC checksums.
|
|||
|
||||
I2C Block Transactions
|
||||
======================
|
||||
|
||||
The following I2C block transactions are supported by the
|
||||
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
|
||||
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
|
||||
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
|
||||
|
||||
|
||||
I2C Block Write
|
||||
===============
|
||||
I2C Block Write: i2c_smbus_write_i2c_block_data()
|
||||
==================================================
|
||||
|
||||
The opposite of the Block Read command, this writes bytes to
|
||||
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.
|
||||
|
||||
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;
|
||||
int result = 0;
|
||||
|
||||
if (i2c->irq == 0)
|
||||
if (i2c->irq == NO_IRQ)
|
||||
{
|
||||
while (!(readb(i2c->base + MPC_I2C_SR) & CSR_MIF)) {
|
||||
schedule();
|
||||
|
@ -329,10 +329,9 @@ static int fsl_i2c_probe(struct platform_device *pdev)
|
|||
return -ENOMEM;
|
||||
|
||||
i2c->irq = platform_get_irq(pdev, 0);
|
||||
if (i2c->irq < 0) {
|
||||
result = -ENXIO;
|
||||
goto fail_get_irq;
|
||||
}
|
||||
if (i2c->irq < 0)
|
||||
i2c->irq = NO_IRQ; /* Use polling */
|
||||
|
||||
i2c->flags = pdata->device_flags;
|
||||
init_waitqueue_head(&i2c->queue);
|
||||
|
||||
|
@ -344,7 +343,7 @@ static int fsl_i2c_probe(struct platform_device *pdev)
|
|||
goto fail_map;
|
||||
}
|
||||
|
||||
if (i2c->irq != 0)
|
||||
if (i2c->irq != NO_IRQ)
|
||||
if ((result = request_irq(i2c->irq, mpc_i2c_isr,
|
||||
IRQF_SHARED, "i2c-mpc", i2c)) < 0) {
|
||||
printk(KERN_ERR
|
||||
|
@ -367,12 +366,11 @@ static int fsl_i2c_probe(struct platform_device *pdev)
|
|||
return result;
|
||||
|
||||
fail_add:
|
||||
if (i2c->irq != 0)
|
||||
if (i2c->irq != NO_IRQ)
|
||||
free_irq(i2c->irq, i2c);
|
||||
fail_irq:
|
||||
iounmap(i2c->base);
|
||||
fail_map:
|
||||
fail_get_irq:
|
||||
kfree(i2c);
|
||||
return result;
|
||||
};
|
||||
|
@ -384,7 +382,7 @@ static int fsl_i2c_remove(struct platform_device *pdev)
|
|||
i2c_del_adapter(&i2c->adap);
|
||||
platform_set_drvdata(pdev, NULL);
|
||||
|
||||
if (i2c->irq != 0)
|
||||
if (i2c->irq != NO_IRQ)
|
||||
free_irq(i2c->irq, i2c);
|
||||
|
||||
iounmap(i2c->base);
|
||||
|
|
|
@ -104,10 +104,31 @@ MODULE_PARM_DESC(force_addr,
|
|||
static int piix4_transaction(void);
|
||||
|
||||
static unsigned short piix4_smba;
|
||||
static int srvrworks_csb5_delay;
|
||||
static struct pci_driver piix4_driver;
|
||||
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",
|
||||
.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));
|
||||
|
||||
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 */
|
||||
if (dmi_check_system(piix4_dmi_table) &&
|
||||
if (dmi_check_system(piix4_dmi_ibm) &&
|
||||
PIIX4_dev->vendor == PCI_VENDOR_ID_INTEL) {
|
||||
dev_err(&PIIX4_dev->dev, "IBM system detected; this module "
|
||||
"may corrupt your serial eeprom! Refusing to load "
|
||||
|
@ -230,10 +263,14 @@ static int piix4_transaction(void)
|
|||
outb_p(inb(SMBHSTCNT) | 0x040, SMBHSTCNT);
|
||||
|
||||
/* 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);
|
||||
temp = inb_p(SMBHSTSTS);
|
||||
} while ((temp & 0x01) && (timeout++ < MAX_TIMEOUT));
|
||||
|
||||
/* If the SMBus is still busy, we give up */
|
||||
if (timeout >= MAX_TIMEOUT) {
|
||||
|
|
|
@ -132,14 +132,14 @@ static const struct i2c_algorithm i2c_sibyte_algo = {
|
|||
/*
|
||||
* 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;
|
||||
|
||||
/* register new adapter to i2c module... */
|
||||
/* Register new adapter to i2c module... */
|
||||
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(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);
|
||||
|
||||
|
||||
static const struct i2c_device_id dummy_id[] = {
|
||||
{ "dummy", 0 },
|
||||
{ },
|
||||
};
|
||||
|
||||
static int dummy_probe(struct i2c_client *client,
|
||||
const struct i2c_device_id *id)
|
||||
{
|
||||
|
@ -342,13 +347,13 @@ static struct i2c_driver dummy_driver = {
|
|||
.driver.name = "dummy",
|
||||
.probe = dummy_probe,
|
||||
.remove = dummy_remove,
|
||||
.id_table = dummy_id,
|
||||
};
|
||||
|
||||
/**
|
||||
* i2c_new_dummy - return a new i2c device bound to a dummy driver
|
||||
* @adapter: the adapter managing the device
|
||||
* @address: seven bit address to be used
|
||||
* @type: optional label used for i2c_client.name
|
||||
* Context: can sleep
|
||||
*
|
||||
* 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.
|
||||
*/
|
||||
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 = {
|
||||
.driver_name = "dummy",
|
||||
.addr = address,
|
||||
I2C_BOARD_INFO("dummy", address),
|
||||
};
|
||||
|
||||
if (type)
|
||||
strlcpy(info.type, type, sizeof info.type);
|
||||
return i2c_new_device(adapter, &info);
|
||||
}
|
||||
EXPORT_SYMBOL_GPL(i2c_new_dummy);
|
||||
|
|
|
@ -885,12 +885,19 @@ static int __exit tcm825x_remove(struct i2c_client *client)
|
|||
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 = {
|
||||
.driver = {
|
||||
.name = TCM825X_NAME,
|
||||
},
|
||||
.probe = tcm825x_probe,
|
||||
.remove = __exit_p(tcm825x_remove),
|
||||
.id_table = tcm825x_id,
|
||||
};
|
||||
|
||||
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 = {
|
||||
.name = "tlv320aic23b",
|
||||
|
@ -175,4 +180,5 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
|||
.command = tlv320aic23b_command,
|
||||
.probe = tlv320aic23b_probe,
|
||||
.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 */
|
||||
strcpy(client->name, desc->name);
|
||||
if (!id)
|
||||
strlcpy(client->name, desc->name, I2C_NAME_SIZE);
|
||||
chip->type = desc-chiplist;
|
||||
chip->shadow.count = desc->registers+1;
|
||||
chip->prevmode = -1;
|
||||
|
@ -1830,6 +1831,15 @@ static int chip_legacy_probe(struct i2c_adapter *adap)
|
|||
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 = {
|
||||
.name = "tvaudio",
|
||||
.driverid = I2C_DRIVERID_TVAUDIO,
|
||||
|
@ -1837,6 +1847,7 @@ static struct v4l2_i2c_driver_data v4l2_i2c_data = {
|
|||
.probe = chip_probe,
|
||||
.remove = chip_remove,
|
||||
.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 */
|
||||
for (i = 1; i < 8; ++i) {
|
||||
s35390a->client[i] = i2c_new_dummy(client->adapter,
|
||||
client->addr + i, "rtc-s35390a");
|
||||
client->addr + i);
|
||||
if (!s35390a->client[i]) {
|
||||
dev_err(&client->dev, "Address %02x unavailable\n",
|
||||
client->addr + i);
|
||||
|
|
|
@ -262,7 +262,7 @@ i2c_new_probed_device(struct i2c_adapter *adap,
|
|||
* client handles for the extra addresses.
|
||||
*/
|
||||
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 *);
|
||||
|
||||
|
|
|
@ -31,6 +31,7 @@ struct v4l2_i2c_driver_data {
|
|||
int (*resume)(struct i2c_client *client);
|
||||
int (*legacy_probe)(struct i2c_adapter *adapter);
|
||||
int legacy_class;
|
||||
const struct i2c_device_id *id_table;
|
||||
};
|
||||
|
||||
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.probe = v4l2_i2c_data.probe;
|
||||
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);
|
||||
if (err)
|
||||
i2c_del_driver(&v4l2_i2c_driver_legacy);
|
||||
|
|
|
@ -36,6 +36,7 @@ struct v4l2_i2c_driver_data {
|
|||
int (*resume)(struct i2c_client *client);
|
||||
int (*legacy_probe)(struct i2c_adapter *adapter);
|
||||
int legacy_class;
|
||||
const struct i2c_device_id *id_table;
|
||||
};
|
||||
|
||||
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.suspend = v4l2_i2c_data.suspend;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in a new issue