From 20a9b6e7c303f2a6f9afe17c0997bc9a3c734442 Mon Sep 17 00:00:00 2001 From: Adrian Bunk Date: Mon, 14 Jul 2008 22:38:22 +0200 Subject: i2c: Remove 3 deprecated bus drivers This patch contains the scheduled removal of i2c-i810, i2c-prosavage and i2c-savage4. Signed-off-by: Adrian Bunk Signed-off-by: Jean Delvare --- Documentation/feature-removal-schedule.txt | 7 ----- Documentation/i2c/busses/i2c-i810 | 47 ------------------------------ Documentation/i2c/busses/i2c-prosavage | 23 --------------- Documentation/i2c/busses/i2c-savage4 | 26 ----------------- 4 files changed, 103 deletions(-) delete mode 100644 Documentation/i2c/busses/i2c-i810 delete mode 100644 Documentation/i2c/busses/i2c-prosavage delete mode 100644 Documentation/i2c/busses/i2c-savage4 (limited to 'Documentation') diff --git a/Documentation/feature-removal-schedule.txt b/Documentation/feature-removal-schedule.txt index 46ece3fba6f9..65a1482457a8 100644 --- a/Documentation/feature-removal-schedule.txt +++ b/Documentation/feature-removal-schedule.txt @@ -222,13 +222,6 @@ Who: Thomas Gleixner --------------------------- -What: i2c-i810, i2c-prosavage and i2c-savage4 -When: May 2008 -Why: These drivers are superseded by i810fb, intelfb and savagefb. -Who: Jean Delvare - ---------------------------- - What (Why): - include/linux/netfilter_ipv4/ipt_TOS.h ipt_tos.h header files (superseded by xt_TOS/xt_tos target & match) diff --git a/Documentation/i2c/busses/i2c-i810 b/Documentation/i2c/busses/i2c-i810 deleted file mode 100644 index 778210ee1583..000000000000 --- a/Documentation/i2c/busses/i2c-i810 +++ /dev/null @@ -1,47 +0,0 @@ -Kernel driver i2c-i810 - -Supported adapters: - * Intel 82810, 82810-DC100, 82810E, and 82815 (GMCH) - * Intel 82845G (GMCH) - -Authors: - Frodo Looijaard , - Philip Edelbrock , - Kyösti Mälkki , - Ralph Metzler , - Mark D. Studebaker - -Main contact: Mark Studebaker - -Description ------------ - -WARNING: If you have an '810' or '815' motherboard, your standard I2C -temperature sensors are most likely on the 801's I2C bus. You want the -i2c-i801 driver for those, not this driver. - -Now for the i2c-i810... - -The GMCH chip contains two I2C interfaces. - -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. It may be connected to a -TV-out chip such as the BT869 or possibly to a digital flat-panel display. - -Features --------- - -Both busses use the i2c-algo-bit driver for 'bit banging' -and support for specific transactions is provided by i2c-algo-bit. - -Issues ------- - -If you enable bus testing in i2c-algo-bit (insmod i2c-algo-bit bit_test=1), -the test may fail; if so, the i2c-i810 driver won't be inserted. However, -we think this has been fixed. diff --git a/Documentation/i2c/busses/i2c-prosavage b/Documentation/i2c/busses/i2c-prosavage deleted file mode 100644 index 703687902511..000000000000 --- a/Documentation/i2c/busses/i2c-prosavage +++ /dev/null @@ -1,23 +0,0 @@ -Kernel driver i2c-prosavage - -Supported adapters: - - S3/VIA KM266/VT8375 aka ProSavage8 - S3/VIA KM133/VT8365 aka Savage4 - -Author: Henk Vergonet - -Description ------------ - -The Savage4 chips contain 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. - -Usefull for gaining access to the TV Encoder chips. - diff --git a/Documentation/i2c/busses/i2c-savage4 b/Documentation/i2c/busses/i2c-savage4 deleted file mode 100644 index 6ecceab618d3..000000000000 --- a/Documentation/i2c/busses/i2c-savage4 +++ /dev/null @@ -1,26 +0,0 @@ -Kernel driver i2c-savage4 - -Supported adapters: - * Savage4 - * Savage2000 - -Authors: - Alexander Wold , - Mark D. Studebaker - -Description ------------ - -The Savage4 chips contain 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 DDC bus is not yet supported because its register -is not directly memory-mapped. - -The second interface is a general-purpose I2C bus. This is the only -interface supported by the driver at the moment. - -- cgit v1.2.3-58-ga151 From 81fded1f79771809059bdfa721ae5ab9114af545 Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 14 Jul 2008 22:38:22 +0200 Subject: i2c: Document standard fault codes Create Documentation/i2c/fault-codes to help standardize fault/error code usage in the I2C stack. It turns out that returning -1 (-EPERM) for everything was not at all helpful. Signed-off-by: David Brownell Signed-off-by: Jean Delvare --- Documentation/i2c/fault-codes | 127 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 127 insertions(+) create mode 100644 Documentation/i2c/fault-codes (limited to 'Documentation') diff --git a/Documentation/i2c/fault-codes b/Documentation/i2c/fault-codes new file mode 100644 index 000000000000..045765c0b9b5 --- /dev/null +++ b/Documentation/i2c/fault-codes @@ -0,0 +1,127 @@ +This is a summary of the most important conventions for use of fault +codes in the I2C/SMBus stack. + + +A "Fault" is not always an "Error" +---------------------------------- +Not all fault reports imply errors; "page faults" should be a familiar +example. Software often retries idempotent operations after transient +faults. There may be fancier recovery schemes that are appropriate in +some cases, such as re-initializing (and maybe resetting). After such +recovery, triggered by a fault report, there is no error. + +In a similar way, sometimes a "fault" code just reports one defined +result for an operation ... it doesn't indicate that anything is wrong +at all, just that the outcome wasn't on the "golden path". + +In short, your I2C driver code may need to know these codes in order +to respond correctly. Other code may need to rely on YOUR code reporting +the right fault code, so that it can (in turn) behave correctly. + + +I2C and SMBus fault codes +------------------------- +These are returned as negative numbers from most calls, with zero or +some positive number indicating a non-fault return. The specific +numbers associated with these symbols differ between architectures, +though most Linux systems use numbering. + +Note that the descriptions here are not exhaustive. There are other +codes that may be returned, and other cases where these codes should +be returned. However, drivers should not return other codes for these +cases (unless the hardware doesn't provide unique fault reports). + +Also, codes returned by adapter probe methods follow rules which are +specific to their host bus (such as PCI, or the platform bus). + + +EAGAIN + Returned by I2C adapters when they lose arbitration in master + transmit mode: some other master was transmitting different + data at the same time. + + Also returned when trying to invoke an I2C operation in an + atomic context, when some task is already using that I2C bus + to execute some other operation. + +EBADMSG + Returned by SMBus logic when an invalid Packet Error Code byte + is received. This code is a CRC covering all bytes in the + transaction, and is sent before the terminating STOP. This + fault is only reported on read transactions; the SMBus slave + may have a way to report PEC mismatches on writes from the + host. Note that even if PECs are in use, you should not rely + on these as the only way to detect incorrect data transfers. + +EBUSY + Returned by SMBus adapters when the bus was busy for longer + than allowed. This usually indicates some device (maybe the + SMBus adapter) needs some fault recovery (such as resetting), + or that the reset was attempted but failed. + +EINVAL + This rather vague error means an invalid parameter has been + detected before any I/O operation was started. Use a more + specific fault code when you can. + + One example would be a driver trying an SMBus Block Write + with block size outside the range of 1-32 bytes. + +EIO + This rather vague error means something went wrong when + performing an I/O operation. Use a more specific fault + code when you can. + +ENODEV + Returned by driver probe() methods. This is a bit more + specific than ENXIO, implying the problem isn't with the + address, but with the device found there. Driver probes + may verify the device returns *correct* responses, and + return this as appropriate. (The driver core will warn + about probe faults other than ENXIO and ENODEV.) + +ENOMEM + Returned by any component that can't allocate memory when + it needs to do so. + +ENXIO + Returned by I2C adapters to indicate that the address phase + of a transfer didn't get an ACK. While it might just mean + an I2C device was temporarily not responding, usually it + means there's nothing listening at that address. + + Returned by driver probe() methods to indicate that they + found no device to bind to. (ENODEV may also be used.) + +EOPNOTSUPP + Returned by an adapter when asked to perform an operation + that it doesn't, or can't, support. + + For example, this would be returned when an adapter that + doesn't support SMBus block transfers is asked to execute + one. In that case, the driver making that request should + have verified that functionality was supported before it + made that block transfer request. + + Similarly, if an I2C adapter can't execute all legal I2C + messages, it should return this when asked to perform a + transaction it can't. (These limitations can't be seen in + the adapter's functionality mask, since the assumption is + that if an adapter supports I2C it supports all of I2C.) + +EPROTO + Returned when slave does not conform to the relevant I2C + or SMBus (or chip-specific) protocol specifications. One + case is when the length of an SMBus block data response + (from the SMBus slave) is outside the range 1-32 bytes. + +ETIMEDOUT + This is returned by drivers when an operation took too much + time, and was aborted before it completed. + + SMBus adapters may return it when an operation took more + time than allowed by the SMBus specification; for example, + when a slave stretches clocks too far. I2C has no such + timeouts, but it's normal for I2C adapters to impose some + arbitrary limits (much longer than SMBus!) too. + -- cgit v1.2.3-58-ga151 From 24a5bb7b1838dc4524dd353224e2aa09c22cac3b Mon Sep 17 00:00:00 2001 From: David Brownell Date: Mon, 14 Jul 2008 22:38:23 +0200 Subject: i2c-core: Return -Errno, not -1 More updates to the I2C stack's fault reporting: make the core stop returning "-1" (usually "-EPERM") for all faults. Instead, pass lower level fault code up the stack, or return some appropriate errno. This patch happens to touch almost exclusively SMBus calls. Signed-off-by: David Brownell Signed-off-by: Jean Delvare --- Documentation/i2c/writing-clients | 8 ++-- drivers/i2c/i2c-core.c | 97 +++++++++++++++++++++------------------ 2 files changed, 57 insertions(+), 48 deletions(-) (limited to 'Documentation') diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index d4cd4126d1ad..ba5d1971f35f 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -598,10 +598,10 @@ be added back later if needed: u8 command, u8 length, u8 *values) -All these transactions return -1 on failure. The 'write' transactions -return 0 on success; the 'read' transactions return the read value, except -for read_block, which returns the number of values read. The block buffers -need not be longer than 32 bytes. +All these transactions return a negative errno value on failure. The 'write' +transactions return 0 on success; the 'read' transactions return the read +value, except for block transactions, which return the number of values +read. The block buffers need not be longer than 32 bytes. You can read the file `smbus-protocol' for more information about the actual SMBus protocol. diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index bb5c215a24e0..937f1dcbf3d7 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -974,7 +974,7 @@ int i2c_transfer(struct i2c_adapter * adap, struct i2c_msg *msgs, int num) return ret; } else { dev_dbg(&adap->dev, "I2C level transfers not supported\n"); - return -ENOSYS; + return -EOPNOTSUPP; } } EXPORT_SYMBOL(i2c_transfer); @@ -1106,7 +1106,7 @@ int i2c_probe(struct i2c_adapter *adapter, dev_warn(&adapter->dev, "SMBus Quick command not supported, " "can't probe for chips\n"); - return -1; + return -EOPNOTSUPP; } /* Probe entries are done second, and are not affected by ignore @@ -1298,7 +1298,7 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) if (rpec != cpec) { pr_debug("i2c-core: Bad PEC 0x%02x vs. 0x%02x\n", rpec, cpec); - return -1; + return -EBADMSG; } return 0; } @@ -1313,11 +1313,12 @@ EXPORT_SYMBOL(i2c_smbus_write_quick); s32 i2c_smbus_read_byte(struct i2c_client *client) { union i2c_smbus_data data; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,0,I2C_SMBUS_BYTE, &data)) - return -1; - else - return data.byte; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, 0, + I2C_SMBUS_BYTE, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte); @@ -1331,11 +1332,12 @@ EXPORT_SYMBOL(i2c_smbus_write_byte); s32 i2c_smbus_read_byte_data(struct i2c_client *client, u8 command) { union i2c_smbus_data data; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, I2C_SMBUS_BYTE_DATA,&data)) - return -1; - else - return data.byte; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BYTE_DATA, &data); + return (status < 0) ? status : data.byte; } EXPORT_SYMBOL(i2c_smbus_read_byte_data); @@ -1352,11 +1354,12 @@ EXPORT_SYMBOL(i2c_smbus_write_byte_data); s32 i2c_smbus_read_word_data(struct i2c_client *client, u8 command) { union i2c_smbus_data data; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, I2C_SMBUS_WORD_DATA, &data)) - return -1; - else - return data.word; + int status; + + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_WORD_DATA, &data); + return (status < 0) ? status : data.word; } EXPORT_SYMBOL(i2c_smbus_read_word_data); @@ -1390,11 +1393,13 @@ s32 i2c_smbus_read_block_data(struct i2c_client *client, u8 command, u8 *values) { union i2c_smbus_data data; + int status; - if (i2c_smbus_xfer(client->adapter, client->addr, client->flags, - I2C_SMBUS_READ, command, - I2C_SMBUS_BLOCK_DATA, &data)) - return -1; + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_BLOCK_DATA, &data); + if (status) + return status; memcpy(values, &data.block[1], data.block[0]); return data.block[0]; @@ -1421,14 +1426,16 @@ s32 i2c_smbus_read_i2c_block_data(struct i2c_client *client, u8 command, u8 length, u8 *values) { union i2c_smbus_data data; + int status; if (length > I2C_SMBUS_BLOCK_MAX) length = I2C_SMBUS_BLOCK_MAX; data.block[0] = length; - if (i2c_smbus_xfer(client->adapter,client->addr,client->flags, - I2C_SMBUS_READ,command, - I2C_SMBUS_I2C_BLOCK_DATA,&data)) - return -1; + status = i2c_smbus_xfer(client->adapter, client->addr, client->flags, + I2C_SMBUS_READ, command, + I2C_SMBUS_I2C_BLOCK_DATA, &data); + if (status < 0) + return status; memcpy(values, &data.block[1], data.block[0]); return data.block[0]; @@ -1469,6 +1476,7 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, }; int i; u8 partial_pec = 0; + int status; msgbuf0[0] = command; switch(size) { @@ -1518,10 +1526,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, } else { msg[0].len = data->block[0] + 2; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 2) { - dev_err(&adapter->dev, "smbus_access called with " - "invalid block write size (%d)\n", - data->block[0]); - return -1; + dev_err(&adapter->dev, + "Invalid block write size %d\n", + data->block[0]); + return -EINVAL; } for (i = 1; i < msg[0].len; i++) msgbuf0[i] = data->block[i-1]; @@ -1531,10 +1539,10 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, num = 2; /* Another special case */ read_write = I2C_SMBUS_READ; if (data->block[0] > I2C_SMBUS_BLOCK_MAX) { - dev_err(&adapter->dev, "%s called with invalid " - "block proc call size (%d)\n", __func__, + dev_err(&adapter->dev, + "Invalid block write size %d\n", data->block[0]); - return -1; + return -EINVAL; } msg[0].len = data->block[0] + 2; for (i = 1; i < msg[0].len; i++) @@ -1549,19 +1557,18 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, } else { msg[0].len = data->block[0] + 1; if (msg[0].len > I2C_SMBUS_BLOCK_MAX + 1) { - dev_err(&adapter->dev, "i2c_smbus_xfer_emulated called with " - "invalid block write size (%d)\n", - data->block[0]); - return -1; + dev_err(&adapter->dev, + "Invalid block write size %d\n", + data->block[0]); + return -EINVAL; } for (i = 1; i <= data->block[0]; i++) msgbuf0[i] = data->block[i]; } break; default: - dev_err(&adapter->dev, "smbus_access called with invalid size (%d)\n", - size); - return -1; + dev_err(&adapter->dev, "Unsupported transaction %d\n", size); + return -EOPNOTSUPP; } i = ((flags & I2C_CLIENT_PEC) && size != I2C_SMBUS_QUICK @@ -1579,13 +1586,15 @@ static s32 i2c_smbus_xfer_emulated(struct i2c_adapter * adapter, u16 addr, msg[num-1].len++; } - if (i2c_transfer(adapter, msg, num) < 0) - return -1; + status = i2c_transfer(adapter, msg, num); + if (status < 0) + return status; /* Check PEC if last message is a read */ if (i && (msg[num-1].flags & I2C_M_RD)) { - if (i2c_smbus_check_pec(partial_pec, &msg[num-1]) < 0) - return -1; + status = i2c_smbus_check_pec(partial_pec, &msg[num-1]); + if (status < 0) + return status; } if (read_write == I2C_SMBUS_READ) -- cgit v1.2.3-58-ga151 From 67c2e66571c383404a5acd08189194da660da942 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 14 Jul 2008 22:38:23 +0200 Subject: i2c: Delete unused function i2c_smbus_write_quick Function i2c_smbus_write_quick has no users left, so we can delete it. Also update the list of these helper functions which are gone but could be added back if needed. Signed-off-by: Jean Delvare --- Documentation/i2c/smbus-protocol | 4 ++-- Documentation/i2c/writing-clients | 14 +++++++------- drivers/i2c/i2c-core.c | 7 ------- include/linux/i2c.h | 1 - 4 files changed, 9 insertions(+), 17 deletions(-) (limited to 'Documentation') diff --git a/Documentation/i2c/smbus-protocol b/Documentation/i2c/smbus-protocol index 03f08fb491cc..24bfb65da17d 100644 --- a/Documentation/i2c/smbus-protocol +++ b/Documentation/i2c/smbus-protocol @@ -42,8 +42,8 @@ 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 Quick Command: i2c_smbus_write_quick() -============================================= +SMBus Quick Command +=================== This sends a single bit to the device, at the place of the Rd/Wr bit. diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index ba5d1971f35f..63722d3c9cdf 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -569,7 +569,6 @@ SMBus communication in terms of it. Never use this function directly! - extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value); extern s32 i2c_smbus_read_byte(struct i2c_client * client); extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value); extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command); @@ -578,20 +577,21 @@ SMBus communication extern s32 i2c_smbus_read_word_data(struct i2c_client * client, u8 command); extern s32 i2c_smbus_write_word_data(struct i2c_client * client, u8 command, u16 value); + extern s32 i2c_smbus_read_block_data(struct i2c_client * client, + u8 command, u8 *values); extern s32 i2c_smbus_write_block_data(struct i2c_client * client, u8 command, u8 length, u8 *values); extern s32 i2c_smbus_read_i2c_block_data(struct i2c_client * client, u8 command, u8 length, u8 *values); - -These ones were removed in Linux 2.6.10 because they had no users, but could -be added back later if needed: - - extern s32 i2c_smbus_read_block_data(struct i2c_client * client, - u8 command, u8 *values); extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, u8 command, u8 length, u8 *values); + +These ones were removed from i2c-core because they had no users, but could +be added back later if needed: + + extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value); extern s32 i2c_smbus_process_call(struct i2c_client * client, u8 command, u16 value); extern s32 i2c_smbus_block_process_call(struct i2c_client *client, diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 937f1dcbf3d7..3695a4a1ab77 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -1303,13 +1303,6 @@ static int i2c_smbus_check_pec(u8 cpec, struct i2c_msg *msg) return 0; } -s32 i2c_smbus_write_quick(struct i2c_client *client, u8 value) -{ - return i2c_smbus_xfer(client->adapter,client->addr,client->flags, - value,0,I2C_SMBUS_QUICK,NULL); -} -EXPORT_SYMBOL(i2c_smbus_write_quick); - s32 i2c_smbus_read_byte(struct i2c_client *client) { union i2c_smbus_data data; diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 8dc730132192..b3695f353f79 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -71,7 +71,6 @@ extern s32 i2c_smbus_xfer (struct i2c_adapter * adapter, u16 addr, /* Now follow the 'nice' access routines. These also document the calling conventions of smbus_access. */ -extern s32 i2c_smbus_write_quick(struct i2c_client * client, u8 value); extern s32 i2c_smbus_read_byte(struct i2c_client * client); extern s32 i2c_smbus_write_byte(struct i2c_client * client, u8 value); extern s32 i2c_smbus_read_byte_data(struct i2c_client * client, u8 command); -- cgit v1.2.3-58-ga151 From 4735c98f8447acb1c8977e2b8024640f7bf36dd6 Mon Sep 17 00:00:00 2001 From: Jean Delvare Date: Mon, 14 Jul 2008 22:38:36 +0200 Subject: i2c: Add detection capability to new-style drivers Add a mechanism to let new-style i2c drivers optionally autodetect devices they would support on selected buses and ask i2c-core to instantiate them. This is a replacement for legacy i2c drivers, much cleaner. Where drivers had to implement both a legacy i2c_driver and a new-style i2c_driver so far, this mechanism makes it possible to get rid of the legacy i2c_driver and implement both enumerated and detected device support with just one (new-style) i2c_driver. Here is a quick conversion guide for these drivers, step by step: * Delete the legacy driver definition, registration and removal. Delete the attach_adapter and detach_client methods of the legacy driver. * Change the prototype of the legacy detect function from static int foo_detect(struct i2c_adapter *adapter, int address, int kind); to static int foo_detect(struct i2c_client *client, int kind, struct i2c_board_info *info); * Set the new-style driver detect callback to this new function, and set its address_data to &addr_data (addr_data is generally provided by I2C_CLIENT_INSMOD.) * Add the appropriate class to the new-style driver. This is typically the class the legacy attach_adapter method was checking for. Class checking is now mandatory (done by i2c-core.) See for the list of available classes. * Remove the i2c_client allocation and freeing from the detect function. A pre-allocated client is now handed to you by i2c-core, and is freed automatically. * Make the detect function fill the type field of the i2c_board_info structure it was passed as a parameter, and return 0, on success. If the detection fails, return -ENODEV. Signed-off-by: Jean Delvare --- Documentation/i2c/writing-clients | 29 +++++ drivers/i2c/i2c-core.c | 223 ++++++++++++++++++++++++++++++++++++-- include/linux/i2c.h | 36 +++++- 3 files changed, 272 insertions(+), 16 deletions(-) (limited to 'Documentation') diff --git a/Documentation/i2c/writing-clients b/Documentation/i2c/writing-clients index 63722d3c9cdf..6b61b3a2e90b 100644 --- a/Documentation/i2c/writing-clients +++ b/Documentation/i2c/writing-clients @@ -44,6 +44,10 @@ static struct i2c_driver foo_driver = { .id_table = foo_ids, .probe = foo_probe, .remove = foo_remove, + /* if device autodetection is needed: */ + .class = I2C_CLASS_SOMETHING, + .detect = foo_detect, + .address_data = &addr_data, /* else, driver uses "legacy" binding model: */ .attach_adapter = foo_attach_adapter, @@ -217,6 +221,31 @@ in the I2C bus driver. You may want to save the returned i2c_client reference for later use. +Device Detection (Standard driver model) +---------------------------------------- + +Sometimes you do not know in advance which I2C devices are connected to +a given I2C bus. This is for example the case of hardware monitoring +devices on a PC's SMBus. In that case, you may want to let your driver +detect supported devices automatically. This is how the legacy model +was working, and is now available as an extension to the standard +driver model (so that we can finally get rid of the legacy model.) + +You simply have to define a detect callback which will attempt to +identify supported devices (returning 0 for supported ones and -ENODEV +for unsupported ones), a list of addresses to probe, and a device type +(or class) so that only I2C buses which may have that type of device +connected (and not otherwise enumerated) will be probed. The i2c +core will then call you back as needed and will instantiate a device +for you for every successful detection. + +Note that this mechanism is purely optional and not suitable for all +devices. You need some reliable way to identify the supported devices +(typically using device-specific, dedicated identification registers), +otherwise misdetections are likely to occur and things can get wrong +quickly. + + Device Deletion (Standard driver model) --------------------------------------- diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index 5e249d758828..0a79f7661017 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -42,7 +42,9 @@ static DEFINE_MUTEX(core_lock); static DEFINE_IDR(i2c_adapter_idr); -#define is_newstyle_driver(d) ((d)->probe || (d)->remove) +#define is_newstyle_driver(d) ((d)->probe || (d)->remove || (d)->detect) + +static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver); /* ------------------------------------------------------------------------- */ @@ -418,6 +420,10 @@ static int i2c_do_add_adapter(struct device_driver *d, void *data) 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); + + /* Let legacy drivers scan this bus for matching devices */ if (driver->attach_adapter) { /* We ignore the return code; if it fails, too bad */ driver->attach_adapter(adap); @@ -457,7 +463,7 @@ static int i2c_register_adapter(struct i2c_adapter *adap) if (adap->nr < __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); - /* let legacy drivers scan this bus for matching devices */ + /* Notify drivers */ dummy = bus_for_each_drv(&i2c_bus_type, NULL, adap, i2c_do_add_adapter); @@ -563,8 +569,19 @@ static int i2c_do_del_adapter(struct device_driver *d, void *data) { struct i2c_driver *driver = to_i2c_driver(d); struct i2c_adapter *adapter = data; + struct i2c_client *client, *_n; int res; + /* Remove the devices we created ourselves */ + list_for_each_entry_safe(client, _n, &driver->clients, detected) { + if (client->adapter == adapter) { + 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) return 0; res = driver->detach_adapter(adapter); @@ -651,7 +668,11 @@ static int __attach_adapter(struct device *dev, void *data) struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; - driver->attach_adapter(adapter); + i2c_detect(adapter, driver); + + /* Legacy drivers scan i2c busses directly */ + if (driver->attach_adapter) + driver->attach_adapter(adapter); return 0; } @@ -695,10 +716,9 @@ int i2c_register_driver(struct module *owner, struct i2c_driver *driver) pr_debug("i2c-core: driver [%s] registered\n", driver->driver.name); - /* legacy drivers scan i2c busses directly */ - if (driver->attach_adapter) - class_for_each_device(&i2c_adapter_class, driver, - __attach_adapter); + INIT_LIST_HEAD(&driver->clients); + /* Walk the adapters that are already present */ + class_for_each_device(&i2c_adapter_class, driver, __attach_adapter); mutex_unlock(&core_lock); return 0; @@ -709,6 +729,17 @@ static int __detach_adapter(struct device *dev, void *data) { struct i2c_adapter *adapter = to_i2c_adapter(dev); struct i2c_driver *driver = data; + struct i2c_client *client, *_n; + + 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 (is_newstyle_driver(driver)) + return 0; /* Have a look at each adapter, if clients of this driver are still * attached. If so, detach them to be able to kill the driver @@ -747,10 +778,7 @@ void i2c_del_driver(struct i2c_driver *driver) { mutex_lock(&core_lock); - /* legacy driver? */ - if (!is_newstyle_driver(driver)) - class_for_each_device(&i2c_adapter_class, driver, - __detach_adapter); + class_for_each_device(&i2c_adapter_class, driver, __detach_adapter); driver_unregister(&driver->driver); pr_debug("i2c-core: driver [%s] unregistered\n", driver->driver.name); @@ -1205,6 +1233,179 @@ int i2c_probe(struct i2c_adapter *adapter, } EXPORT_SYMBOL(i2c_probe); +/* Separate detection function for new-style drivers */ +static int i2c_detect_address(struct i2c_client *temp_client, int kind, + struct i2c_driver *driver) +{ + struct i2c_board_info info; + struct i2c_adapter *adapter = temp_client->adapter; + int addr = temp_client->addr; + int err; + + /* Make sure the address is valid */ + if (addr < 0x03 || addr > 0x77) { + dev_warn(&adapter->dev, "Invalid probe address 0x%02x\n", + addr); + return -EINVAL; + } + + /* Skip if already in use */ + 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; + + /* 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); + if (err) { + /* -ENODEV is returned if the detection fails. We catch it + here as this isn't an error. */ + return err == -ENODEV ? 0 : err; + } + + /* Consistency check */ + if (info.type[0] == '\0') { + dev_err(&adapter->dev, "%s detection function provided " + "no name for 0x%x\n", driver->driver.name, + addr); + } else { + struct i2c_client *client; + + /* Detection succeeded, instantiate the device */ + dev_dbg(&adapter->dev, "Creating %s at 0x%02x\n", + info.type, info.addr); + client = i2c_new_device(adapter, &info); + if (client) + list_add_tail(&client->detected, &driver->clients); + else + dev_err(&adapter->dev, "Failed creating %s at 0x%02x\n", + info.type, info.addr); + } + return 0; +} + +static int i2c_detect(struct i2c_adapter *adapter, struct i2c_driver *driver) +{ + const struct i2c_client_address_data *address_data; + struct i2c_client *temp_client; + int i, err = 0; + int adap_id = i2c_adapter_id(adapter); + + address_data = driver->address_data; + if (!driver->detect || !address_data) + return 0; + + /* Set up a temporary client to help detect callback */ + temp_client = kzalloc(sizeof(struct i2c_client), GFP_KERNEL); + if (!temp_client) + 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 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) + goto exit_free; + + dev_warn(&adapter->dev, "SMBus Quick command not supported, " + "can't probe for chips\n"); + err = -EOPNOTSUPP; + goto exit_free; + } + + /* Stop here if the classes do not match */ + if (!(adapter->class & driver->class)) + 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); + if (err) + goto exit_free; + } + + exit_free: + kfree(temp_client); + return err; +} + struct i2c_client * i2c_new_probed_device(struct i2c_adapter *adap, struct i2c_board_info *info, diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 50cbab4b62b0..08be0d21864c 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -45,6 +45,7 @@ struct i2c_adapter; struct i2c_client; struct i2c_driver; union i2c_smbus_data; +struct i2c_board_info; /* * The master routines are the ones normally used to transmit data to devices @@ -94,15 +95,33 @@ extern s32 i2c_smbus_write_i2c_block_data(struct i2c_client * client, u8 command, u8 length, const u8 *values); -/* - * A driver is capable of handling one or more physical devices present on - * I2C adapters. This information is used to inform the driver of adapter - * events. +/** + * struct i2c_driver - represent an I2C device driver + * @class: What kind of i2c device we instantiate (for detect) + * @detect: Callback for device detection + * @address_data: The I2C addresses to probe, ignore or force (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. * The driver.name field should be set to the name of this driver. + * + * For automatic device detection, both @detect and @address_data must + * be defined. @class should also be set, otherwise only devices forced + * with module parameters will be created. The detect function must + * fill at least the name field of the i2c_board_info structure it is + * handed upon successful detection, and possibly also the flags field. + * + * If @detect is missing, the driver will still work fine for enumerated + * devices. Detected devices simply won't be supported. This is expected + * for the many I2C/SMBus devices which can't be detected reliably, and + * the ones which can always be enumerated in practice. + * + * The i2c_client structure which is handed to the @detect callback is + * not a real i2c_client. It is initialized just enough so that you can + * call i2c_smbus_read_byte_data and friends on it. Don't do anything + * else with it. In particular, calling dev_dbg and friends on it is + * not allowed. */ - struct i2c_driver { int id; unsigned int class; @@ -142,6 +161,11 @@ struct i2c_driver { struct device_driver driver; const struct i2c_device_id *id_table; + + /* Device detection callback for automatic device creation */ + int (*detect)(struct i2c_client *, int kind, struct i2c_board_info *); + const struct i2c_client_address_data *address_data; + struct list_head clients; }; #define to_i2c_driver(d) container_of(d, struct i2c_driver, driver) @@ -157,6 +181,7 @@ struct i2c_driver { * @dev: Driver model device node for the slave. * @irq: indicates the IRQ generated by this device (if any) * @list: list of active/busy clients (DEPRECATED) + * @detected: member of an i2c_driver.clients list * @released: used to synchronize client releases & detaches and references * * An i2c_client identifies a single device (i.e. chip) connected to an @@ -174,6 +199,7 @@ struct i2c_client { struct device dev; /* the device structure */ int irq; /* irq issued by device */ struct list_head list; /* DEPRECATED */ + struct list_head detected; struct completion released; }; #define to_i2c_client(d) container_of(d, struct i2c_client, dev) -- cgit v1.2.3-58-ga151